@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.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
|
|
3
3
|
// src/OhhwellsBridge.tsx
|
|
4
|
-
import React12, { useCallback as useCallback12, useEffect as useEffect17, useLayoutEffect as
|
|
4
|
+
import React12, { useCallback as useCallback12, useEffect as useEffect17, useLayoutEffect as useLayoutEffect7, useRef as useRef14, useState as useState18 } from "react";
|
|
5
5
|
import { createRoot as createRoot3 } from "react-dom/client";
|
|
6
6
|
import { flushSync as flushSync3 } from "react-dom";
|
|
7
7
|
|
|
@@ -6649,6 +6649,21 @@ function pricingCardFeatureCount(tree, index) {
|
|
|
6649
6649
|
const target = findPricingCollection(tree)?.children?.[index];
|
|
6650
6650
|
return target ? pricingFeatureList(target).length : 0;
|
|
6651
6651
|
}
|
|
6652
|
+
function prevailingFeatureIcon(features) {
|
|
6653
|
+
const counts = /* @__PURE__ */ new Map();
|
|
6654
|
+
for (const row of features) {
|
|
6655
|
+
const key = `${row.icon ?? ""}|${row.iconColor ?? ""}`;
|
|
6656
|
+
const entry = counts.get(key) ?? { count: 0, ...row.icon ? { icon: row.icon } : {}, ...row.iconColor ? { iconColor: row.iconColor } : {} };
|
|
6657
|
+
entry.count += 1;
|
|
6658
|
+
counts.set(key, entry);
|
|
6659
|
+
}
|
|
6660
|
+
let best = null;
|
|
6661
|
+
for (const entry of counts.values()) {
|
|
6662
|
+
if (!best || entry.count > best.count) best = entry;
|
|
6663
|
+
}
|
|
6664
|
+
if (!best) return {};
|
|
6665
|
+
return { ...best.icon ? { icon: best.icon } : {}, ...best.iconColor ? { iconColor: best.iconColor } : {} };
|
|
6666
|
+
}
|
|
6652
6667
|
function addPricingCardFeature(tree, index, text) {
|
|
6653
6668
|
return withPricingCollection(tree, (collection) => {
|
|
6654
6669
|
const children = collection.children;
|
|
@@ -6657,7 +6672,7 @@ function addPricingCardFeature(tree, index, text) {
|
|
|
6657
6672
|
const features = pricingFeatureList(target);
|
|
6658
6673
|
if (features.length >= PRICING_FEATURES_MAX) return false;
|
|
6659
6674
|
target.slots = target.slots ?? {};
|
|
6660
|
-
target.slots.features = [...features, { text }];
|
|
6675
|
+
target.slots.features = [...features, { text, ...prevailingFeatureIcon(features) }];
|
|
6661
6676
|
return true;
|
|
6662
6677
|
});
|
|
6663
6678
|
}
|
|
@@ -7269,6 +7284,23 @@ function applyCustomCodeToHead(content) {
|
|
|
7269
7284
|
if (beforeNodes.length > 0) document.head.append(...beforeNodes);
|
|
7270
7285
|
}
|
|
7271
7286
|
|
|
7287
|
+
// src/lib/node-font-size.ts
|
|
7288
|
+
var TEXT_NODE_TYPES = /* @__PURE__ */ new Set(["text", "text/rich", "plain", "link"]);
|
|
7289
|
+
function escapeKey(key) {
|
|
7290
|
+
return typeof CSS !== "undefined" && typeof CSS.escape === "function" ? CSS.escape(key) : key.replace(/["\\]/g, "\\$&");
|
|
7291
|
+
}
|
|
7292
|
+
function measureNodeFontSize(key, type, root) {
|
|
7293
|
+
if (!TEXT_NODE_TYPES.has(type)) return void 0;
|
|
7294
|
+
const el = root.querySelector(`[data-ohw-editable][data-ohw-key="${escapeKey(key)}"]`);
|
|
7295
|
+
if (!el) return void 0;
|
|
7296
|
+
const size = Number.parseFloat(window.getComputedStyle(el).fontSize);
|
|
7297
|
+
return Number.isFinite(size) && size > 0 ? Math.round(size) : void 0;
|
|
7298
|
+
}
|
|
7299
|
+
function withNodeFontSize(node, root) {
|
|
7300
|
+
const fontSize = measureNodeFontSize(node.key, node.type, root);
|
|
7301
|
+
return fontSize === void 0 ? node : { ...node, fontSize };
|
|
7302
|
+
}
|
|
7303
|
+
|
|
7272
7304
|
// src/lib/selectNavContainer.ts
|
|
7273
7305
|
function isOnScreen(el) {
|
|
7274
7306
|
const rect = el.getBoundingClientRect();
|
|
@@ -7857,7 +7889,7 @@ var AI_MOBILE_CSS = [
|
|
|
7857
7889
|
// page's first section. Top only (bottom needs no nav clearance); ~96px approximates the
|
|
7858
7890
|
// template nav's own height (measured ~94px) — there's no shared `--ohw-header-h` var to read
|
|
7859
7891
|
// an exact figure from (no live measurement exists), so this is a safe approximation, not a
|
|
7860
|
-
// pixel-exact fit. Horizontal spacing already comes from `data-ai-
|
|
7892
|
+
// pixel-exact fit. Horizontal spacing already comes from `data-ai-section-inner`.
|
|
7861
7893
|
'[data-ai-overlay-clearance] [data-ai-overlap-layer="overlay"]{padding-top:96px}',
|
|
7862
7894
|
// A full-bleed carousel's height is pure arithmetic: it spans the whole window, so 16/9 turns
|
|
7863
7895
|
// window width straight into height. Measured at 16/9 it came out ~90% of the viewport at EVERY
|
|
@@ -7873,8 +7905,10 @@ var AI_MOBILE_CSS = [
|
|
|
7873
7905
|
"[data-ai-section]{overflow-x:hidden}",
|
|
7874
7906
|
// `:not([data-ai-full-bleed])`: this `!important` gutter beat the inline `padding: 0` that a
|
|
7875
7907
|
// full-bleed section's container sets, so a carousel/media hero that is edge-to-edge on desktop
|
|
7876
|
-
// still got a 20px band of section background down both sides on a phone.
|
|
7877
|
-
|
|
7908
|
+
// still got a 20px band of section background down both sides on a phone. The footer's own
|
|
7909
|
+
// container keeps the unguarded rule below — `data-ai-full-bleed` can never appear on it.
|
|
7910
|
+
"[data-ai-section-inner]:not([data-ai-full-bleed]){padding:0 20px !important}",
|
|
7911
|
+
"[data-ai-container]{padding:0 20px !important}",
|
|
7878
7912
|
"[data-ai-row]{display:flex !important;flex-direction:column !important;align-items:stretch !important}",
|
|
7879
7913
|
"[data-ai-cell]{width:100%;min-width:0}",
|
|
7880
7914
|
// The rule above turns every row into a COLUMN flex container on phones, which silently breaks
|
|
@@ -8079,6 +8113,31 @@ function pricingCardEmphasis(featured, ctx, hasBg) {
|
|
|
8079
8113
|
function textAttrs(ctx, path) {
|
|
8080
8114
|
return ctx.keyFor ? { "data-ohw-key": ctx.keyFor(path), "data-ohw-editable": "text" } : {};
|
|
8081
8115
|
}
|
|
8116
|
+
var AI_RESPONSIVE_CSS = [
|
|
8117
|
+
"@media (max-width: 960px) {",
|
|
8118
|
+
" [data-ai-responsive] [data-ai-grid] { grid-template-columns: repeat(2, 1fr) !important; }",
|
|
8119
|
+
' [data-ai-responsive] [data-ai-grid="1"] { grid-template-columns: 1fr !important; }',
|
|
8120
|
+
"}",
|
|
8121
|
+
"@media (max-width: 640px) {",
|
|
8122
|
+
" [data-ai-responsive] [data-ai-grid] { grid-template-columns: 1fr !important; }",
|
|
8123
|
+
" [data-ai-responsive] [data-ai-columns] > * { grid-column: 1 / -1 !important; }",
|
|
8124
|
+
// Group containers flatten to a column on phones; span placements come along for free.
|
|
8125
|
+
// `:not([data-ai-group="overlap"])` for the same reason as the twin pair in AI_MOBILE_CSS — see
|
|
8126
|
+
// the comment there. This sheet's copy is the narrower selector, so without the exemption it
|
|
8127
|
+
// flattens an `overlap` hero below 640px even though the other rule stands down: measured a 390px
|
|
8128
|
+
// viewport with the heading/CTA in flow *under* the image, 219px of section background where the
|
|
8129
|
+
// layered text used to be.
|
|
8130
|
+
' [data-ai-responsive] [data-ai-group]:not([data-ai-group="overlap"]) { display: flex !important; flex-direction: column !important; }',
|
|
8131
|
+
' [data-ai-responsive] [data-ai-group]:not([data-ai-group="overlap"]) > * { grid-column: auto !important; }',
|
|
8132
|
+
// `:not([data-ai-full-bleed])` for the same reason as the twin rule in AI_MOBILE_CSS: this one
|
|
8133
|
+
// is narrower (0,2,0 vs 0,1,0) and also `!important`, so without the guard it wins outright and
|
|
8134
|
+
// a full-bleed hero gets its 20px side band back below 640px only — the one width where the
|
|
8135
|
+
// other rule had already been taught to stand down.
|
|
8136
|
+
" [data-ai-responsive] [data-ai-section-inner]:not([data-ai-full-bleed]) { padding-left: 20px !important; padding-right: 20px !important; }",
|
|
8137
|
+
" [data-ai-responsive] { overflow-x: hidden; }",
|
|
8138
|
+
" [data-ai-responsive] img { max-width: 100%; }",
|
|
8139
|
+
"}"
|
|
8140
|
+
].join("\n");
|
|
8082
8141
|
var TRANSPARENT_PX = "data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7";
|
|
8083
8142
|
function MediaBox({
|
|
8084
8143
|
refValue,
|
|
@@ -8133,7 +8192,7 @@ function MediaBox({
|
|
|
8133
8192
|
position: fill ? "absolute" : void 0,
|
|
8134
8193
|
inset: fill ? 0 : void 0,
|
|
8135
8194
|
width: fill ? "100%" : fixedSize ? "auto" : "100%",
|
|
8136
|
-
height: fill ? "100%" : void 0,
|
|
8195
|
+
height: fill ? "100%" : fixedSize ? height : void 0,
|
|
8137
8196
|
aspectRatio: fill ? void 0 : aspectRatio,
|
|
8138
8197
|
minHeight: fill || fixedSize ? void 0 : height ?? (aspectRatio ? void 0 : 180),
|
|
8139
8198
|
borderRadius: radius,
|
|
@@ -9629,7 +9688,7 @@ function CollectionBlock({ node, ctx, path }) {
|
|
|
9629
9688
|
return /* @__PURE__ */ jsx(
|
|
9630
9689
|
"div",
|
|
9631
9690
|
{
|
|
9632
|
-
"data-ai-grid":
|
|
9691
|
+
"data-ai-grid": String(itemsPerRow),
|
|
9633
9692
|
"data-ohw-pricing-collection": isPricing ? "" : void 0,
|
|
9634
9693
|
style: {
|
|
9635
9694
|
display: "grid",
|
|
@@ -9931,7 +9990,7 @@ function renderNode(node, ctx, path, ambientAlign) {
|
|
|
9931
9990
|
},
|
|
9932
9991
|
children: [
|
|
9933
9992
|
i > 0 && ctx.heroOverlapFullBleed ? (
|
|
9934
|
-
// The section's `data-ai-
|
|
9993
|
+
// The section's `data-ai-section-inner` gave up its max-width/gutter so the base
|
|
9935
9994
|
// layer (this group's i===0 sibling) can span edge-to-edge — reintroduced here,
|
|
9936
9995
|
// scoped to just the overlay text, so a heading/copy/CTA stack doesn't stretch
|
|
9937
9996
|
// the full section width instead of reading at the usual content width.
|
|
@@ -10350,6 +10409,7 @@ function AiTreeRenderer({
|
|
|
10350
10409
|
...fillHeight ? { "data-ai-fill-height": "" } : {},
|
|
10351
10410
|
...needsOverlayClearance ? { "data-ai-overlay-clearance": "" } : {},
|
|
10352
10411
|
...bgAttrs,
|
|
10412
|
+
"data-ai-responsive": "",
|
|
10353
10413
|
style: {
|
|
10354
10414
|
position: "relative",
|
|
10355
10415
|
padding: `${padCss} 0`,
|
|
@@ -10363,12 +10423,13 @@ function AiTreeRenderer({
|
|
|
10363
10423
|
...fillHeight ? { display: "grid" } : {}
|
|
10364
10424
|
},
|
|
10365
10425
|
children: [
|
|
10366
|
-
|
|
10426
|
+
/* @__PURE__ */ jsx("style", { children: AI_RESPONSIVE_CSS }),
|
|
10367
10427
|
/* @__PURE__ */ jsx("style", { children: AI_MOBILE_CSS }),
|
|
10428
|
+
isOverlay && backgroundUrl && /* @__PURE__ */ jsx("div", { style: { position: "absolute", inset: 0, background: `rgba(255,255,255,${overlayAlpha})` } }),
|
|
10368
10429
|
/* @__PURE__ */ jsx(
|
|
10369
10430
|
"div",
|
|
10370
10431
|
{
|
|
10371
|
-
"data-ai-
|
|
10432
|
+
"data-ai-section-inner": "",
|
|
10372
10433
|
...fullBleedMedia ? { "data-ai-full-bleed": "" } : {},
|
|
10373
10434
|
style: {
|
|
10374
10435
|
position: "relative",
|
|
@@ -10385,7 +10446,7 @@ function AiTreeRenderer({
|
|
|
10385
10446
|
children: tree.rows.map((row, r2) => /* @__PURE__ */ jsx(
|
|
10386
10447
|
"div",
|
|
10387
10448
|
{
|
|
10388
|
-
"data-ai-
|
|
10449
|
+
"data-ai-columns": "",
|
|
10389
10450
|
style: {
|
|
10390
10451
|
display: "grid",
|
|
10391
10452
|
gridTemplateColumns: "repeat(12, 1fr)",
|
|
@@ -11047,9 +11108,10 @@ function applyAiSectionsToDom(state, options) {
|
|
|
11047
11108
|
if (existing && existing.serialized === serialized && existing.container.isConnected) {
|
|
11048
11109
|
continue;
|
|
11049
11110
|
}
|
|
11050
|
-
const isNewMount = !existing || !existing.container.isConnected;
|
|
11051
11111
|
let container = existing?.container;
|
|
11112
|
+
let isNewMount = false;
|
|
11052
11113
|
if (!container || !container.isConnected) {
|
|
11114
|
+
isNewMount = true;
|
|
11053
11115
|
existing?.root.unmount();
|
|
11054
11116
|
container?.remove();
|
|
11055
11117
|
container = document.createElement("div");
|
|
@@ -17208,7 +17270,7 @@ function apiBase() {
|
|
|
17208
17270
|
function bridgeVersion() {
|
|
17209
17271
|
try {
|
|
17210
17272
|
if (true) {
|
|
17211
|
-
return "0.1.
|
|
17273
|
+
return "0.1.160-next.427";
|
|
17212
17274
|
}
|
|
17213
17275
|
} catch {
|
|
17214
17276
|
}
|
|
@@ -17222,7 +17284,7 @@ function stampBridgeVersionOnDocument() {
|
|
|
17222
17284
|
return;
|
|
17223
17285
|
}
|
|
17224
17286
|
try {
|
|
17225
|
-
const v = true ? "0.1.
|
|
17287
|
+
const v = true ? "0.1.160-next.427" : "";
|
|
17226
17288
|
if (v) {
|
|
17227
17289
|
document.documentElement.setAttribute("data-ohw-bridge-version", v);
|
|
17228
17290
|
window.__OHW_BRIDGE_VERSION__ = v;
|
|
@@ -17900,6 +17962,7 @@ function MediaOverlay({
|
|
|
17900
17962
|
(prev) => prev && prev.fullWidth === width && prev.height === height ? prev : { fullWidth: width, height }
|
|
17901
17963
|
);
|
|
17902
17964
|
}, [isVideo]);
|
|
17965
|
+
const replaceLabel = isVideo ? "Replace video" : hover.elementType === "bg-image" ? "Replace background" : "Replace image";
|
|
17903
17966
|
const replaceMode = buttonSize ? replaceButtonMode({ width: rect.width, height: rect.height }, buttonSize) : "none";
|
|
17904
17967
|
const box = {
|
|
17905
17968
|
position: "fixed",
|
|
@@ -17998,11 +18061,10 @@ function MediaOverlay({
|
|
|
17998
18061
|
className: "flex items-center justify-center cursor-pointer",
|
|
17999
18062
|
style: {
|
|
18000
18063
|
...box,
|
|
18001
|
-
//
|
|
18002
|
-
//
|
|
18003
|
-
//
|
|
18004
|
-
|
|
18005
|
-
pointerEvents: hover.hasTextOverlap || cueOnly ? "none" : "auto",
|
|
18064
|
+
// Visual only. `pointer-events: auto` on this full-bleed rect covered the navbar
|
|
18065
|
+
// (hero bg includes the absolute TopNav) and swallowed CTA press-drag. Text overlay
|
|
18066
|
+
// and cueOnly also need clicks to fall through — Replace / video controls opt back in.
|
|
18067
|
+
pointerEvents: "none",
|
|
18006
18068
|
// Selected: a firm component ring with no wash, so the image reads as chosen rather
|
|
18007
18069
|
// than hovered. Hover keeps the existing tinted preview.
|
|
18008
18070
|
boxShadow: selected ? "inset 0 0 0 2px var(--color-bridge-primary)" : "inset 0 0 0 1.5px var(--color-bridge-primary)",
|
|
@@ -18029,17 +18091,17 @@ function MediaOverlay({
|
|
|
18029
18091
|
},
|
|
18030
18092
|
children: [
|
|
18031
18093
|
isVideo ? /* @__PURE__ */ jsx17(Film, { size: 14 }) : /* @__PURE__ */ jsx17(ImageIcon, { size: 14 }),
|
|
18032
|
-
|
|
18094
|
+
replaceLabel
|
|
18033
18095
|
]
|
|
18034
18096
|
}
|
|
18035
18097
|
),
|
|
18036
|
-
replaceMode
|
|
18098
|
+
showChrome && replaceMode !== "none" && /* @__PURE__ */ jsxs8(
|
|
18037
18099
|
Button,
|
|
18038
18100
|
{
|
|
18039
18101
|
"data-ohw-media-overlay": "",
|
|
18040
18102
|
variant: "outline",
|
|
18041
18103
|
size: "sm",
|
|
18042
|
-
"aria-label":
|
|
18104
|
+
"aria-label": replaceLabel,
|
|
18043
18105
|
className: "gap-1.5 cursor-pointer hover:bg-background",
|
|
18044
18106
|
style: {
|
|
18045
18107
|
...OVERLAY_BUTTON_STYLE,
|
|
@@ -18062,7 +18124,7 @@ function MediaOverlay({
|
|
|
18062
18124
|
},
|
|
18063
18125
|
children: [
|
|
18064
18126
|
isVideo ? /* @__PURE__ */ jsx17(Film, { size: 14 }) : /* @__PURE__ */ jsx17(ImageIcon, { size: 14 }),
|
|
18065
|
-
replaceMode === "full" ?
|
|
18127
|
+
replaceMode === "full" ? replaceLabel : null
|
|
18066
18128
|
]
|
|
18067
18129
|
}
|
|
18068
18130
|
)
|
|
@@ -18655,8 +18717,24 @@ function AiSectionOverlay({
|
|
|
18655
18717
|
}
|
|
18656
18718
|
|
|
18657
18719
|
// src/ui/ai-section/AiMediaStripOverlay.tsx
|
|
18658
|
-
import { useCallback as useCallback3, useEffect as useEffect6, useRef as useRef5, useState as useState8 } from "react";
|
|
18659
|
-
import {
|
|
18720
|
+
import { useCallback as useCallback3, useEffect as useEffect6, useLayoutEffect as useLayoutEffect4, useRef as useRef5, useState as useState8 } from "react";
|
|
18721
|
+
import {
|
|
18722
|
+
AlignCenter,
|
|
18723
|
+
AlignLeft,
|
|
18724
|
+
AlignRight,
|
|
18725
|
+
ArrowLeft as ArrowLeft2,
|
|
18726
|
+
ArrowRight as ArrowRight2,
|
|
18727
|
+
Check as Check2,
|
|
18728
|
+
ChevronDown as ChevronDown3,
|
|
18729
|
+
Image as ImageIcon2,
|
|
18730
|
+
ImageMinus,
|
|
18731
|
+
ImagePlus,
|
|
18732
|
+
Link as LinkIcon,
|
|
18733
|
+
Minus,
|
|
18734
|
+
Palette,
|
|
18735
|
+
Plus as Plus2,
|
|
18736
|
+
Star
|
|
18737
|
+
} from "lucide-react";
|
|
18660
18738
|
|
|
18661
18739
|
// src/lib/ai-media-strip-tree.ts
|
|
18662
18740
|
var MEDIA_STRIP_ITEM_MIN = 1;
|
|
@@ -18770,14 +18848,6 @@ function setMediaStripItemAsset(tree, index, assetId) {
|
|
|
18770
18848
|
return true;
|
|
18771
18849
|
});
|
|
18772
18850
|
}
|
|
18773
|
-
function setMediaStripItemAlt(tree, index, alt) {
|
|
18774
|
-
return withMediaStrip(tree, (block) => {
|
|
18775
|
-
const items = block.items;
|
|
18776
|
-
if (index < 0 || index >= items.length) return false;
|
|
18777
|
-
items[index] = { ...items[index], alt };
|
|
18778
|
-
return true;
|
|
18779
|
-
});
|
|
18780
|
-
}
|
|
18781
18851
|
function setMediaStripItemLink(tree, index, link) {
|
|
18782
18852
|
return withMediaStrip(tree, (block) => {
|
|
18783
18853
|
const items = block.items;
|
|
@@ -18795,11 +18865,117 @@ function setMediaStripItemLink(tree, index, link) {
|
|
|
18795
18865
|
});
|
|
18796
18866
|
}
|
|
18797
18867
|
|
|
18868
|
+
// src/ui/dialog.tsx
|
|
18869
|
+
import * as React9 from "react";
|
|
18870
|
+
import { Dialog as DialogPrimitive } from "radix-ui";
|
|
18871
|
+
import { X as X2 } from "lucide-react";
|
|
18872
|
+
import { jsx as jsx20, jsxs as jsxs11 } from "react/jsx-runtime";
|
|
18873
|
+
function Dialog2({
|
|
18874
|
+
...props
|
|
18875
|
+
}) {
|
|
18876
|
+
return /* @__PURE__ */ jsx20(DialogPrimitive.Root, { "data-slot": "dialog", ...props });
|
|
18877
|
+
}
|
|
18878
|
+
function DialogPortal({
|
|
18879
|
+
...props
|
|
18880
|
+
}) {
|
|
18881
|
+
return /* @__PURE__ */ jsx20(DialogPrimitive.Portal, { ...props });
|
|
18882
|
+
}
|
|
18883
|
+
function DialogOverlay({
|
|
18884
|
+
className,
|
|
18885
|
+
...props
|
|
18886
|
+
}) {
|
|
18887
|
+
return /* @__PURE__ */ jsx20(
|
|
18888
|
+
DialogPrimitive.Overlay,
|
|
18889
|
+
{
|
|
18890
|
+
"data-slot": "dialog-overlay",
|
|
18891
|
+
"data-ohw-link-modal-root": "",
|
|
18892
|
+
className: cn("fixed inset-0 z-[2147483646] bg-black/50", className),
|
|
18893
|
+
...props
|
|
18894
|
+
}
|
|
18895
|
+
);
|
|
18896
|
+
}
|
|
18897
|
+
var DialogContent = React9.forwardRef(
|
|
18898
|
+
({ className, children, showCloseButton = true, container, ...props }, ref) => {
|
|
18899
|
+
const positionMode = container ? "absolute" : "fixed";
|
|
18900
|
+
return /* @__PURE__ */ jsxs11(DialogPortal, { container: container ?? void 0, children: [
|
|
18901
|
+
/* @__PURE__ */ jsx20(DialogOverlay, { className: cn(positionMode, "inset-0") }),
|
|
18902
|
+
/* @__PURE__ */ jsxs11(
|
|
18903
|
+
DialogPrimitive.Content,
|
|
18904
|
+
{
|
|
18905
|
+
ref,
|
|
18906
|
+
"data-slot": "dialog-content",
|
|
18907
|
+
className: cn(
|
|
18908
|
+
positionMode,
|
|
18909
|
+
"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",
|
|
18910
|
+
"rounded-xl border border-border bg-background font-sans shadow-lg outline-none",
|
|
18911
|
+
container ? "max-h-[calc(100%-32px)]" : "max-h-[calc(100vh-32px)]",
|
|
18912
|
+
className
|
|
18913
|
+
),
|
|
18914
|
+
onMouseDown: (e) => e.stopPropagation(),
|
|
18915
|
+
...props,
|
|
18916
|
+
children: [
|
|
18917
|
+
children,
|
|
18918
|
+
showCloseButton ? /* @__PURE__ */ jsx20(
|
|
18919
|
+
DialogPrimitive.Close,
|
|
18920
|
+
{
|
|
18921
|
+
type: "button",
|
|
18922
|
+
className: "absolute right-[9px] top-[9px] rounded-sm p-1.5 text-foreground hover:bg-muted/50",
|
|
18923
|
+
"aria-label": "Close",
|
|
18924
|
+
children: /* @__PURE__ */ jsx20(X2, { size: 16, "aria-hidden": true })
|
|
18925
|
+
}
|
|
18926
|
+
) : null
|
|
18927
|
+
]
|
|
18928
|
+
}
|
|
18929
|
+
)
|
|
18930
|
+
] });
|
|
18931
|
+
}
|
|
18932
|
+
);
|
|
18933
|
+
DialogContent.displayName = DialogPrimitive.Content.displayName;
|
|
18934
|
+
function DialogHeader({
|
|
18935
|
+
className,
|
|
18936
|
+
...props
|
|
18937
|
+
}) {
|
|
18938
|
+
return /* @__PURE__ */ jsx20("div", { className: cn("flex flex-col gap-1.5", className), ...props });
|
|
18939
|
+
}
|
|
18940
|
+
function DialogFooter({
|
|
18941
|
+
className,
|
|
18942
|
+
...props
|
|
18943
|
+
}) {
|
|
18944
|
+
return /* @__PURE__ */ jsx20(
|
|
18945
|
+
"div",
|
|
18946
|
+
{
|
|
18947
|
+
className: cn("flex items-center justify-end gap-2", className),
|
|
18948
|
+
...props
|
|
18949
|
+
}
|
|
18950
|
+
);
|
|
18951
|
+
}
|
|
18952
|
+
var DialogTitle = React9.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx20(
|
|
18953
|
+
DialogPrimitive.Title,
|
|
18954
|
+
{
|
|
18955
|
+
ref,
|
|
18956
|
+
className: cn(
|
|
18957
|
+
"text-lg font-semibold leading-none tracking-tight text-card-foreground",
|
|
18958
|
+
className
|
|
18959
|
+
),
|
|
18960
|
+
...props
|
|
18961
|
+
}
|
|
18962
|
+
));
|
|
18963
|
+
DialogTitle.displayName = DialogPrimitive.Title.displayName;
|
|
18964
|
+
var DialogDescription = React9.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx20(
|
|
18965
|
+
DialogPrimitive.Description,
|
|
18966
|
+
{
|
|
18967
|
+
ref,
|
|
18968
|
+
className: cn("text-sm text-muted-foreground", className),
|
|
18969
|
+
...props
|
|
18970
|
+
}
|
|
18971
|
+
));
|
|
18972
|
+
DialogDescription.displayName = DialogPrimitive.Description.displayName;
|
|
18973
|
+
var DialogClose = DialogPrimitive.Close;
|
|
18974
|
+
|
|
18798
18975
|
// src/ui/ai-section/AiMediaStripOverlay.tsx
|
|
18799
|
-
import { Fragment as Fragment7, jsx as
|
|
18800
|
-
var PRIMARY3 = "#0885FE";
|
|
18801
|
-
var
|
|
18802
|
-
var OHW_BLUE_DARK = `color-mix(in srgb, var(--ohw-primary, ${PRIMARY3}) 60%, #000000)`;
|
|
18976
|
+
import { Fragment as Fragment7, jsx as jsx21, jsxs as jsxs12 } from "react/jsx-runtime";
|
|
18977
|
+
var PRIMARY3 = "var(--ohw-primary, #0885FE)";
|
|
18978
|
+
var CHROME_SELECTOR = "[data-ohw-toolbar], [data-ohw-edit-chrome], [data-ohw-item-interaction], [data-ohw-link-modal-root], [data-ohw-section-picker], [data-ohw-ai-review], [data-ohw-more-menu]";
|
|
18803
18979
|
function findMediaStripItemElement(sectionId, index) {
|
|
18804
18980
|
const sectionEl = findByInstanceId(sectionId);
|
|
18805
18981
|
if (!sectionEl) return null;
|
|
@@ -18809,14 +18985,35 @@ function findMediaStripItemElement(sectionId, index) {
|
|
|
18809
18985
|
}
|
|
18810
18986
|
return null;
|
|
18811
18987
|
}
|
|
18812
|
-
function
|
|
18813
|
-
|
|
18988
|
+
function itemRefFromTarget(target) {
|
|
18989
|
+
if (!(target instanceof Element)) return null;
|
|
18990
|
+
if (target.closest(CHROME_SELECTOR)) return null;
|
|
18991
|
+
const itemEl = target.closest("[data-ohw-media-strip-item]");
|
|
18992
|
+
if (!itemEl) return null;
|
|
18993
|
+
const sectionEl = itemEl.closest("[data-ohw-section]");
|
|
18994
|
+
const unit = sectionEl ? movableUnit(sectionEl) : null;
|
|
18995
|
+
const sectionId = unit ? instanceIdOf(unit) || null : null;
|
|
18996
|
+
const index = Number(itemEl.dataset.ohwMediaStripIndex);
|
|
18997
|
+
if (!sectionId || Number.isNaN(index)) return null;
|
|
18998
|
+
return { sectionId, index };
|
|
18999
|
+
}
|
|
19000
|
+
function sameRef(a, b) {
|
|
19001
|
+
return a?.sectionId === b?.sectionId && a?.index === b?.index;
|
|
19002
|
+
}
|
|
19003
|
+
function rectOf(el) {
|
|
18814
19004
|
if (!el) return null;
|
|
18815
19005
|
const r2 = el.getBoundingClientRect();
|
|
18816
19006
|
if (r2.width <= 0 || r2.height <= 0) return null;
|
|
18817
19007
|
return { top: r2.top, left: r2.left, width: r2.width, height: r2.height };
|
|
18818
19008
|
}
|
|
18819
|
-
function
|
|
19009
|
+
function readRect2(ref) {
|
|
19010
|
+
return rectOf(ref && findMediaStripItemElement(ref.sectionId, ref.index));
|
|
19011
|
+
}
|
|
19012
|
+
function readStripRect(ref) {
|
|
19013
|
+
const item = ref && findMediaStripItemElement(ref.sectionId, ref.index);
|
|
19014
|
+
return rectOf(item?.closest("[data-ohw-media-strip]") ?? item);
|
|
19015
|
+
}
|
|
19016
|
+
function useLiveItemRect(ref, strip = false) {
|
|
18820
19017
|
const [rect, setRect] = useState8(null);
|
|
18821
19018
|
useEffect6(() => {
|
|
18822
19019
|
if (!ref) {
|
|
@@ -18824,7 +19021,7 @@ function useLiveItemRect(ref) {
|
|
|
18824
19021
|
return;
|
|
18825
19022
|
}
|
|
18826
19023
|
const update = () => {
|
|
18827
|
-
const next = readRect2(ref);
|
|
19024
|
+
const next = strip ? readStripRect(ref) : readRect2(ref);
|
|
18828
19025
|
setRect(
|
|
18829
19026
|
(prev) => prev && next && prev.top === next.top && prev.left === next.left && prev.width === next.width && prev.height === next.height ? prev : next
|
|
18830
19027
|
);
|
|
@@ -18839,9 +19036,49 @@ function useLiveItemRect(ref) {
|
|
|
18839
19036
|
window.removeEventListener("resize", update);
|
|
18840
19037
|
clearInterval(interval);
|
|
18841
19038
|
};
|
|
18842
|
-
}, [ref?.sectionId, ref?.index]);
|
|
19039
|
+
}, [ref?.sectionId, ref?.index, strip]);
|
|
18843
19040
|
return rect;
|
|
18844
19041
|
}
|
|
19042
|
+
var TOOLBAR_STRIP_GAP = 52;
|
|
19043
|
+
var TOOLBAR_STRIP_GAP_MOBILE = 42;
|
|
19044
|
+
var TOOLBAR_EDGE_MARGIN2 = 4;
|
|
19045
|
+
function StripToolbarSlot({ stripRect, children }) {
|
|
19046
|
+
const slotRef = useRef5(null);
|
|
19047
|
+
const [shift, setShift] = useState8(0);
|
|
19048
|
+
const centerX = stripRect.left + stripRect.width / 2;
|
|
19049
|
+
useLayoutEffect4(() => {
|
|
19050
|
+
const slot = slotRef.current;
|
|
19051
|
+
if (!slot) return;
|
|
19052
|
+
const clamp = () => {
|
|
19053
|
+
const w = slot.offsetWidth;
|
|
19054
|
+
if (w <= 0) return;
|
|
19055
|
+
const half = w / 2;
|
|
19056
|
+
const clamped = Math.max(TOOLBAR_EDGE_MARGIN2 + half, Math.min(centerX, window.innerWidth - TOOLBAR_EDGE_MARGIN2 - half));
|
|
19057
|
+
setShift((prev) => Math.abs(prev - (clamped - centerX)) < 0.5 ? prev : clamped - centerX);
|
|
19058
|
+
};
|
|
19059
|
+
clamp();
|
|
19060
|
+
const ro = new ResizeObserver(clamp);
|
|
19061
|
+
ro.observe(slot);
|
|
19062
|
+
return () => ro.disconnect();
|
|
19063
|
+
}, [centerX, children]);
|
|
19064
|
+
const mobile = window.innerWidth <= 480;
|
|
19065
|
+
return /* @__PURE__ */ jsx21(
|
|
19066
|
+
"div",
|
|
19067
|
+
{
|
|
19068
|
+
ref: slotRef,
|
|
19069
|
+
"data-ohw-bridge": "",
|
|
19070
|
+
"data-ohw-item-interaction": "",
|
|
19071
|
+
className: "pointer-events-auto fixed",
|
|
19072
|
+
style: {
|
|
19073
|
+
top: stripRect.top - (mobile ? TOOLBAR_STRIP_GAP_MOBILE : TOOLBAR_STRIP_GAP),
|
|
19074
|
+
left: centerX + shift,
|
|
19075
|
+
transform: "translate(-50%, -100%)",
|
|
19076
|
+
zIndex: 2147483645
|
|
19077
|
+
},
|
|
19078
|
+
children
|
|
19079
|
+
}
|
|
19080
|
+
);
|
|
19081
|
+
}
|
|
18845
19082
|
function requestValidateTree(postToParent2, tree) {
|
|
18846
19083
|
return new Promise((resolve) => {
|
|
18847
19084
|
const id = `ai-validate-${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 8)}`;
|
|
@@ -18878,221 +19115,177 @@ function requestAssetPick(postToParent2) {
|
|
|
18878
19115
|
postToParent2({ type: "ow:asset-pick", id });
|
|
18879
19116
|
});
|
|
18880
19117
|
}
|
|
18881
|
-
function
|
|
19118
|
+
function ToolbarAction({
|
|
18882
19119
|
label,
|
|
18883
19120
|
onClick,
|
|
18884
|
-
disabled,
|
|
18885
|
-
active
|
|
19121
|
+
disabled = false,
|
|
19122
|
+
active = false,
|
|
19123
|
+
children
|
|
18886
19124
|
}) {
|
|
18887
|
-
|
|
18888
|
-
|
|
18889
|
-
{
|
|
18890
|
-
|
|
18891
|
-
|
|
18892
|
-
disabled,
|
|
18893
|
-
style: {
|
|
18894
|
-
height: 28,
|
|
18895
|
-
padding: "0 10px",
|
|
18896
|
-
display: "inline-flex",
|
|
18897
|
-
alignItems: "center",
|
|
18898
|
-
gap: 4,
|
|
18899
|
-
borderRadius: 999,
|
|
18900
|
-
border: "none",
|
|
18901
|
-
cursor: disabled ? "default" : "pointer",
|
|
18902
|
-
background: active ? OHW_BLUE_DARK : "#ffffff",
|
|
18903
|
-
color: active ? "#ffffff" : OHW_BLUE_DARK,
|
|
18904
|
-
opacity: disabled ? 0.4 : 1,
|
|
18905
|
-
fontSize: 12,
|
|
18906
|
-
lineHeight: "16px",
|
|
18907
|
-
fontFamily: "Figtree, ui-sans-serif, system-ui, sans-serif",
|
|
18908
|
-
whiteSpace: "nowrap",
|
|
18909
|
-
flex: "0 0 auto"
|
|
18910
|
-
},
|
|
18911
|
-
children: label
|
|
18912
|
-
}
|
|
18913
|
-
);
|
|
19125
|
+
const button = /* @__PURE__ */ jsx21(CustomToolbarButton, { type: "button", "aria-label": label, disabled, active, onClick, className: "size-8", children });
|
|
19126
|
+
return /* @__PURE__ */ jsxs12(Tooltip, { children: [
|
|
19127
|
+
/* @__PURE__ */ jsx21(TooltipTrigger, { asChild: true, children: disabled ? /* @__PURE__ */ jsx21("span", { className: "inline-flex", children: button }) : button }),
|
|
19128
|
+
/* @__PURE__ */ jsx21(TooltipContent, { side: "bottom", sideOffset: 8, children: label })
|
|
19129
|
+
] });
|
|
18914
19130
|
}
|
|
18915
|
-
function
|
|
18916
|
-
|
|
18917
|
-
useEffect6(() => setDraft(value), [value]);
|
|
18918
|
-
return /* @__PURE__ */ jsxs11(
|
|
18919
|
-
"div",
|
|
18920
|
-
{
|
|
18921
|
-
style: {
|
|
18922
|
-
display: "flex",
|
|
18923
|
-
alignItems: "center",
|
|
18924
|
-
gap: 6,
|
|
18925
|
-
height: 28,
|
|
18926
|
-
padding: "0 12px",
|
|
18927
|
-
borderRadius: 999,
|
|
18928
|
-
background: "#ffffff",
|
|
18929
|
-
width: "100%",
|
|
18930
|
-
maxWidth: 260,
|
|
18931
|
-
boxSizing: "border-box"
|
|
18932
|
-
},
|
|
18933
|
-
children: [
|
|
18934
|
-
/* @__PURE__ */ jsx20(
|
|
18935
|
-
"span",
|
|
18936
|
-
{
|
|
18937
|
-
style: {
|
|
18938
|
-
flex: "0 0 auto",
|
|
18939
|
-
color: OHW_BLUE_DARK,
|
|
18940
|
-
fontSize: 10,
|
|
18941
|
-
fontWeight: 700,
|
|
18942
|
-
textTransform: "uppercase",
|
|
18943
|
-
letterSpacing: 0.4
|
|
18944
|
-
},
|
|
18945
|
-
children: "Alt"
|
|
18946
|
-
}
|
|
18947
|
-
),
|
|
18948
|
-
/* @__PURE__ */ jsx20(
|
|
18949
|
-
"input",
|
|
18950
|
-
{
|
|
18951
|
-
type: "text",
|
|
18952
|
-
value: draft,
|
|
18953
|
-
onChange: (e) => setDraft(e.target.value),
|
|
18954
|
-
onBlur: () => {
|
|
18955
|
-
if (draft !== value) onCommit(draft);
|
|
18956
|
-
},
|
|
18957
|
-
onKeyDown: (e) => {
|
|
18958
|
-
if (e.key === "Enter") e.currentTarget.blur();
|
|
18959
|
-
if (e.key === "Escape") {
|
|
18960
|
-
setDraft(value);
|
|
18961
|
-
e.currentTarget.blur();
|
|
18962
|
-
}
|
|
18963
|
-
},
|
|
18964
|
-
placeholder: "Describe this image",
|
|
18965
|
-
"aria-label": "Image alt text",
|
|
18966
|
-
style: {
|
|
18967
|
-
flex: 1,
|
|
18968
|
-
minWidth: 0,
|
|
18969
|
-
border: "none",
|
|
18970
|
-
outline: "none",
|
|
18971
|
-
background: "transparent",
|
|
18972
|
-
fontSize: 12,
|
|
18973
|
-
lineHeight: "16px",
|
|
18974
|
-
fontFamily: "Figtree, ui-sans-serif, system-ui, sans-serif",
|
|
18975
|
-
color: "#1f2937"
|
|
18976
|
-
}
|
|
18977
|
-
}
|
|
18978
|
-
)
|
|
18979
|
-
]
|
|
18980
|
-
}
|
|
18981
|
-
);
|
|
19131
|
+
function ToolbarSeparator() {
|
|
19132
|
+
return /* @__PURE__ */ jsx21("span", { "aria-hidden": true, className: "mx-0.5 block h-6 w-px shrink-0 bg-border" });
|
|
18982
19133
|
}
|
|
18983
|
-
|
|
18984
|
-
|
|
18985
|
-
|
|
18986
|
-
|
|
18987
|
-
|
|
18988
|
-
|
|
18989
|
-
|
|
18990
|
-
|
|
18991
|
-
|
|
18992
|
-
|
|
18993
|
-
|
|
18994
|
-
|
|
18995
|
-
|
|
18996
|
-
|
|
18997
|
-
|
|
18998
|
-
|
|
18999
|
-
|
|
19000
|
-
|
|
19001
|
-
|
|
19002
|
-
|
|
19003
|
-
|
|
19004
|
-
|
|
19005
|
-
|
|
19006
|
-
|
|
19007
|
-
|
|
19008
|
-
|
|
19009
|
-
}, [value]);
|
|
19010
|
-
const commit = () => {
|
|
19011
|
-
const next = draft.trim();
|
|
19012
|
-
if (next === value) return setInvalid(false);
|
|
19013
|
-
if (next && !HTTP_URL_RE.test(next)) return setInvalid(true);
|
|
19014
|
-
setInvalid(false);
|
|
19015
|
-
onCommit(next);
|
|
19016
|
-
};
|
|
19017
|
-
return /* @__PURE__ */ jsxs11(
|
|
19018
|
-
"div",
|
|
19019
|
-
{
|
|
19020
|
-
style: {
|
|
19021
|
-
display: "flex",
|
|
19022
|
-
alignItems: "center",
|
|
19023
|
-
gap: 6,
|
|
19024
|
-
height: 28,
|
|
19025
|
-
padding: "0 12px",
|
|
19026
|
-
borderRadius: 999,
|
|
19027
|
-
background: "#ffffff",
|
|
19028
|
-
width: "100%",
|
|
19029
|
-
maxWidth: 260,
|
|
19030
|
-
boxSizing: "border-box",
|
|
19031
|
-
boxShadow: invalid ? "inset 0 0 0 1.5px #EF4444" : "none"
|
|
19032
|
-
},
|
|
19033
|
-
children: [
|
|
19034
|
-
/* @__PURE__ */ jsx20(
|
|
19035
|
-
"span",
|
|
19036
|
-
{
|
|
19037
|
-
style: {
|
|
19038
|
-
flex: "0 0 auto",
|
|
19039
|
-
color: OHW_BLUE_DARK,
|
|
19040
|
-
fontSize: 10,
|
|
19041
|
-
fontWeight: 700,
|
|
19042
|
-
textTransform: "uppercase",
|
|
19043
|
-
letterSpacing: 0.4
|
|
19044
|
-
},
|
|
19045
|
-
children: "Link"
|
|
19046
|
-
}
|
|
19047
|
-
),
|
|
19048
|
-
/* @__PURE__ */ jsx20(
|
|
19049
|
-
"input",
|
|
19134
|
+
function OptionMenu({
|
|
19135
|
+
label,
|
|
19136
|
+
value,
|
|
19137
|
+
options,
|
|
19138
|
+
onChange
|
|
19139
|
+
}) {
|
|
19140
|
+
const current = options.find((o) => o.value === value) ?? options[0];
|
|
19141
|
+
return /* @__PURE__ */ jsxs12("div", { className: "flex items-center gap-1.5 pl-1.5", children: [
|
|
19142
|
+
/* @__PURE__ */ jsx21("span", { className: "text-xs text-muted-foreground", children: label }),
|
|
19143
|
+
/* @__PURE__ */ jsxs12(DropdownMenu, { modal: false, children: [
|
|
19144
|
+
/* @__PURE__ */ jsx21(DropdownMenuTrigger, { asChild: true, children: /* @__PURE__ */ jsxs12(
|
|
19145
|
+
"button",
|
|
19146
|
+
{
|
|
19147
|
+
type: "button",
|
|
19148
|
+
"aria-label": label,
|
|
19149
|
+
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",
|
|
19150
|
+
children: [
|
|
19151
|
+
/* @__PURE__ */ jsx21("span", { className: "flex-1 text-left", children: current.label }),
|
|
19152
|
+
/* @__PURE__ */ jsx21(ChevronDown3, { size: 16, style: { pointerEvents: "none" } })
|
|
19153
|
+
]
|
|
19154
|
+
}
|
|
19155
|
+
) }),
|
|
19156
|
+
/* @__PURE__ */ jsx21(DropdownMenuContent, { align: "end", sideOffset: 8, className: "w-[132px] min-w-[132px] p-1", children: options.map((option) => {
|
|
19157
|
+
const selected = option.value === value;
|
|
19158
|
+
return /* @__PURE__ */ jsxs12(
|
|
19159
|
+
DropdownMenuItem,
|
|
19050
19160
|
{
|
|
19051
|
-
|
|
19052
|
-
|
|
19053
|
-
|
|
19054
|
-
|
|
19055
|
-
|
|
19056
|
-
|
|
19057
|
-
|
|
19058
|
-
|
|
19059
|
-
|
|
19060
|
-
|
|
19061
|
-
|
|
19062
|
-
|
|
19063
|
-
|
|
19064
|
-
|
|
19065
|
-
|
|
19066
|
-
|
|
19067
|
-
|
|
19068
|
-
|
|
19069
|
-
|
|
19070
|
-
|
|
19071
|
-
|
|
19072
|
-
|
|
19073
|
-
|
|
19074
|
-
|
|
19075
|
-
|
|
19076
|
-
|
|
19077
|
-
|
|
19078
|
-
|
|
19079
|
-
|
|
19080
|
-
|
|
19161
|
+
role: "menuitemradio",
|
|
19162
|
+
"aria-checked": selected,
|
|
19163
|
+
onSelect: () => onChange(option.value),
|
|
19164
|
+
className: cn("grid grid-cols-[1fr_16px] gap-2 py-2 pl-2 pr-2 text-[13px]", selected && "bg-muted"),
|
|
19165
|
+
children: [
|
|
19166
|
+
/* @__PURE__ */ jsx21("span", { children: option.label }),
|
|
19167
|
+
selected && /* @__PURE__ */ jsx21(Check2, { size: 16, className: "text-bridge-primary" })
|
|
19168
|
+
]
|
|
19169
|
+
},
|
|
19170
|
+
option.value
|
|
19171
|
+
);
|
|
19172
|
+
}) })
|
|
19173
|
+
] })
|
|
19174
|
+
] });
|
|
19175
|
+
}
|
|
19176
|
+
var VARIANTS = [
|
|
19177
|
+
{ value: "logos", label: "Logos" },
|
|
19178
|
+
{ value: "reel", label: "Reel" }
|
|
19179
|
+
];
|
|
19180
|
+
var ALIGNS = [
|
|
19181
|
+
{ value: "left", label: "Align left", Icon: AlignLeft },
|
|
19182
|
+
{ value: "center", label: "Align center", Icon: AlignCenter },
|
|
19183
|
+
{ value: "right", label: "Align right", Icon: AlignRight }
|
|
19184
|
+
];
|
|
19185
|
+
var HOVERS = [
|
|
19186
|
+
{ value: "none", label: "None" },
|
|
19187
|
+
{ value: "lift", label: "Lift" },
|
|
19188
|
+
{ value: "zoom", label: "Zoom" },
|
|
19189
|
+
{ value: "fade", label: "Fade" }
|
|
19190
|
+
];
|
|
19191
|
+
var HTTP_URL_RE = /^https?:\/\/\S+$/i;
|
|
19192
|
+
function LinkModal({
|
|
19193
|
+
href,
|
|
19194
|
+
linkTarget,
|
|
19195
|
+
onClose,
|
|
19196
|
+
onSave
|
|
19197
|
+
}) {
|
|
19198
|
+
const [draft, setDraft] = useState8(href);
|
|
19199
|
+
const [newTab, setNewTab] = useState8(linkTarget !== "same-tab");
|
|
19200
|
+
const [invalid, setInvalid] = useState8(false);
|
|
19201
|
+
const save = () => {
|
|
19202
|
+
const next = draft.trim();
|
|
19203
|
+
if (next && !HTTP_URL_RE.test(next)) {
|
|
19204
|
+
setInvalid(true);
|
|
19205
|
+
return;
|
|
19081
19206
|
}
|
|
19082
|
-
|
|
19207
|
+
onSave(next, newTab ? "new-tab" : "same-tab");
|
|
19208
|
+
onClose();
|
|
19209
|
+
};
|
|
19210
|
+
return /* @__PURE__ */ jsx21(Dialog2, { open: true, onOpenChange: (open) => !open && onClose(), children: /* @__PURE__ */ jsxs12(DialogContent, { "data-ohw-link-modal-root": "", className: "max-w-[400px] gap-4 p-5", children: [
|
|
19211
|
+
/* @__PURE__ */ jsx21(DialogHeader, { children: /* @__PURE__ */ jsx21(DialogTitle, { className: "text-base", children: "Image link" }) }),
|
|
19212
|
+
/* @__PURE__ */ jsxs12("div", { className: "flex flex-col gap-3", children: [
|
|
19213
|
+
/* @__PURE__ */ jsx21(
|
|
19214
|
+
"input",
|
|
19215
|
+
{
|
|
19216
|
+
autoFocus: true,
|
|
19217
|
+
type: "text",
|
|
19218
|
+
inputMode: "url",
|
|
19219
|
+
value: draft,
|
|
19220
|
+
onChange: (e) => {
|
|
19221
|
+
setDraft(e.target.value);
|
|
19222
|
+
setInvalid(false);
|
|
19223
|
+
},
|
|
19224
|
+
onKeyDown: (e) => {
|
|
19225
|
+
if (e.key === "Enter") save();
|
|
19226
|
+
},
|
|
19227
|
+
placeholder: "https://example.com",
|
|
19228
|
+
"aria-label": "Image link URL",
|
|
19229
|
+
"aria-invalid": invalid,
|
|
19230
|
+
className: cn(
|
|
19231
|
+
"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",
|
|
19232
|
+
invalid && "border-destructive focus:border-destructive"
|
|
19233
|
+
)
|
|
19234
|
+
}
|
|
19235
|
+
),
|
|
19236
|
+
invalid && /* @__PURE__ */ jsx21("p", { className: "text-xs text-destructive", children: "Enter a full URL starting with http:// or https://" }),
|
|
19237
|
+
/* @__PURE__ */ jsxs12("label", { className: "flex items-center gap-2 text-[13px] text-foreground", children: [
|
|
19238
|
+
/* @__PURE__ */ jsx21("input", { type: "checkbox", checked: newTab, onChange: (e) => setNewTab(e.target.checked) }),
|
|
19239
|
+
"Open in new tab"
|
|
19240
|
+
] })
|
|
19241
|
+
] }),
|
|
19242
|
+
/* @__PURE__ */ jsxs12(DialogFooter, { children: [
|
|
19243
|
+
href && /* @__PURE__ */ jsx21(
|
|
19244
|
+
"button",
|
|
19245
|
+
{
|
|
19246
|
+
type: "button",
|
|
19247
|
+
onClick: () => {
|
|
19248
|
+
onSave("", "new-tab");
|
|
19249
|
+
onClose();
|
|
19250
|
+
},
|
|
19251
|
+
className: "mr-auto rounded-[6px] px-3 py-2 text-[13px] font-medium text-destructive transition-colors hover:bg-muted",
|
|
19252
|
+
children: "Remove link"
|
|
19253
|
+
}
|
|
19254
|
+
),
|
|
19255
|
+
/* @__PURE__ */ jsx21(
|
|
19256
|
+
"button",
|
|
19257
|
+
{
|
|
19258
|
+
type: "button",
|
|
19259
|
+
onClick: onClose,
|
|
19260
|
+
className: "rounded-[6px] px-3 py-2 text-[13px] font-medium text-foreground transition-colors hover:bg-muted",
|
|
19261
|
+
children: "Cancel"
|
|
19262
|
+
}
|
|
19263
|
+
),
|
|
19264
|
+
/* @__PURE__ */ jsx21(
|
|
19265
|
+
"button",
|
|
19266
|
+
{
|
|
19267
|
+
type: "button",
|
|
19268
|
+
onClick: save,
|
|
19269
|
+
className: "rounded-[6px] bg-bridge-primary px-3 py-2 text-[13px] font-medium text-primary-foreground transition-opacity hover:opacity-90",
|
|
19270
|
+
children: "Save"
|
|
19271
|
+
}
|
|
19272
|
+
)
|
|
19273
|
+
] })
|
|
19274
|
+
] }) });
|
|
19083
19275
|
}
|
|
19084
19276
|
function MediaStripToolbar({
|
|
19085
19277
|
entry,
|
|
19086
19278
|
index,
|
|
19087
19279
|
pending,
|
|
19088
19280
|
error,
|
|
19281
|
+
itemEditOn,
|
|
19282
|
+
onToggleItemEdit,
|
|
19089
19283
|
onSetVariant,
|
|
19090
19284
|
onSetAlign,
|
|
19091
19285
|
onSetHover,
|
|
19092
19286
|
onSetTreatment,
|
|
19093
19287
|
onResize,
|
|
19094
|
-
|
|
19095
|
-
onSetLink,
|
|
19288
|
+
onOpenLink,
|
|
19096
19289
|
onAddItem,
|
|
19097
19290
|
onRemoveItem,
|
|
19098
19291
|
onChangeImage,
|
|
@@ -19101,81 +19294,102 @@ function MediaStripToolbar({
|
|
|
19101
19294
|
}) {
|
|
19102
19295
|
const items = mediaStripItems(entry.tree);
|
|
19103
19296
|
const itemCount = items.length;
|
|
19104
|
-
const currentAlt = items[index]?.alt ?? "";
|
|
19105
|
-
const currentHref = items[index]?.href ?? "";
|
|
19106
|
-
const currentTarget = items[index]?.linkTarget === "same-tab" ? "same-tab" : "new-tab";
|
|
19107
19297
|
const slots = findMediaStripSlots(entry.tree);
|
|
19108
19298
|
const variant = slots?.variant === "reel" ? "reel" : "logos";
|
|
19109
19299
|
const align = slots?.align === "left" || slots?.align === "right" ? slots.align : "center";
|
|
19110
19300
|
const hover = slots?.hover === "none" || slots?.hover === "lift" || slots?.hover === "zoom" || slots?.hover === "fade" ? slots.hover : "lift";
|
|
19111
19301
|
const treatment = slots?.treatment === "color" || slots?.treatment === "grayscale" ? slots.treatment : variant === "logos" ? "grayscale" : "color";
|
|
19112
19302
|
const sizeValue = variant === "logos" ? typeof slots?.logoMaxHeight === "number" ? slots.logoMaxHeight : 48 : typeof slots?.cardWidth === "number" ? slots.cardWidth : 240;
|
|
19113
|
-
const
|
|
19114
|
-
const
|
|
19115
|
-
|
|
19116
|
-
gap: 6,
|
|
19117
|
-
flexWrap: "nowrap",
|
|
19118
|
-
justifyContent: "center",
|
|
19119
|
-
overflowX: "auto",
|
|
19120
|
-
WebkitOverflowScrolling: "touch",
|
|
19121
|
-
width: "100%",
|
|
19122
|
-
scrollbarWidth: "none"
|
|
19123
|
-
} : { display: "flex", gap: 6, flexWrap: "nowrap", justifyContent: "center" };
|
|
19124
|
-
return /* @__PURE__ */ jsxs11(
|
|
19303
|
+
const mobile = window.innerWidth <= 480;
|
|
19304
|
+
const gatedLabel = (label) => itemEditOn ? label : "Turn on the star to edit this image";
|
|
19305
|
+
return /* @__PURE__ */ jsx21(TooltipProvider, { delayDuration: 0, children: /* @__PURE__ */ jsxs12(
|
|
19125
19306
|
"div",
|
|
19126
19307
|
{
|
|
19127
19308
|
"data-ohw-bridge": "",
|
|
19128
19309
|
"data-ohw-toolbar": "",
|
|
19129
19310
|
onMouseDown: (e) => e.stopPropagation(),
|
|
19130
|
-
|
|
19131
|
-
|
|
19132
|
-
flexDirection: "column",
|
|
19133
|
-
gap: 6,
|
|
19134
|
-
alignItems: "center",
|
|
19135
|
-
background: OHW_BLUE,
|
|
19136
|
-
padding: 8,
|
|
19137
|
-
borderRadius: 12,
|
|
19138
|
-
boxShadow: "0 8px 24px rgba(0,0,0,0.25)",
|
|
19139
|
-
pointerEvents: pending ? "none" : "auto",
|
|
19140
|
-
opacity: pending ? 0.6 : 1,
|
|
19141
|
-
maxWidth: isMobile ? "calc(100vw - 24px)" : "none"
|
|
19142
|
-
},
|
|
19311
|
+
className: cn("flex flex-col items-center gap-1.5 font-sans", pending && "pointer-events-none opacity-60"),
|
|
19312
|
+
style: { maxWidth: mobile ? "calc(100vw - 24px)" : void 0 },
|
|
19143
19313
|
children: [
|
|
19144
|
-
/* @__PURE__ */
|
|
19145
|
-
|
|
19146
|
-
|
|
19147
|
-
|
|
19148
|
-
|
|
19149
|
-
|
|
19150
|
-
|
|
19151
|
-
|
|
19152
|
-
|
|
19153
|
-
|
|
19154
|
-
|
|
19155
|
-
|
|
19156
|
-
|
|
19157
|
-
|
|
19158
|
-
|
|
19159
|
-
|
|
19160
|
-
|
|
19161
|
-
|
|
19162
|
-
|
|
19163
|
-
|
|
19164
|
-
|
|
19165
|
-
|
|
19166
|
-
|
|
19167
|
-
|
|
19168
|
-
|
|
19169
|
-
|
|
19170
|
-
|
|
19171
|
-
|
|
19172
|
-
|
|
19173
|
-
|
|
19174
|
-
|
|
19175
|
-
|
|
19314
|
+
/* @__PURE__ */ jsxs12(
|
|
19315
|
+
"div",
|
|
19316
|
+
{
|
|
19317
|
+
className: cn(
|
|
19318
|
+
"flex items-center gap-1 rounded-[10px] border border-border bg-background p-1 whitespace-nowrap",
|
|
19319
|
+
"shadow-[0px_10px_15px_-3px_rgba(0,0,0,0.1),0px_4px_6px_-4px_rgba(0,0,0,0.1)]",
|
|
19320
|
+
mobile ? "flex-wrap justify-center" : "flex-nowrap"
|
|
19321
|
+
),
|
|
19322
|
+
children: [
|
|
19323
|
+
/* @__PURE__ */ jsxs12(Tooltip, { children: [
|
|
19324
|
+
/* @__PURE__ */ jsx21(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsx21(
|
|
19325
|
+
CustomToolbarButton,
|
|
19326
|
+
{
|
|
19327
|
+
type: "button",
|
|
19328
|
+
"aria-label": itemEditOn ? "Done editing this image" : "Edit this image",
|
|
19329
|
+
"aria-pressed": itemEditOn,
|
|
19330
|
+
onClick: onToggleItemEdit,
|
|
19331
|
+
className: "group size-8",
|
|
19332
|
+
children: /* @__PURE__ */ jsx21(
|
|
19333
|
+
Star,
|
|
19334
|
+
{
|
|
19335
|
+
size: 16,
|
|
19336
|
+
fill: "currentColor",
|
|
19337
|
+
strokeWidth: 0,
|
|
19338
|
+
className: cn(
|
|
19339
|
+
"transition-colors",
|
|
19340
|
+
itemEditOn ? "text-[#f59e0b] group-hover:text-[#d97706]" : "text-[#d6d3d1] group-hover:text-[#fbbf24]"
|
|
19341
|
+
),
|
|
19342
|
+
style: { pointerEvents: "none" }
|
|
19343
|
+
}
|
|
19344
|
+
)
|
|
19345
|
+
}
|
|
19346
|
+
) }),
|
|
19347
|
+
/* @__PURE__ */ jsx21(TooltipContent, { side: "bottom", sideOffset: 8, children: itemEditOn ? "Done editing this image" : "Edit this image" })
|
|
19348
|
+
] }),
|
|
19349
|
+
/* @__PURE__ */ jsx21(ToolbarSeparator, {}),
|
|
19350
|
+
/* @__PURE__ */ jsx21(ToolbarAction, { label: gatedLabel("Change image"), onClick: onChangeImage, disabled: !itemEditOn, children: /* @__PURE__ */ jsx21(ImageIcon2, { size: 16, style: { pointerEvents: "none" } }) }),
|
|
19351
|
+
/* @__PURE__ */ jsx21(ToolbarAction, { label: gatedLabel("Link"), onClick: onOpenLink, disabled: !itemEditOn, children: /* @__PURE__ */ jsx21(LinkIcon, { size: 16, style: { pointerEvents: "none" } }) }),
|
|
19352
|
+
/* @__PURE__ */ jsx21(ToolbarAction, { label: gatedLabel("Move left"), onClick: onMoveLeft, disabled: !itemEditOn || index <= 0, children: /* @__PURE__ */ jsx21(ArrowLeft2, { size: 16, style: { pointerEvents: "none" } }) }),
|
|
19353
|
+
/* @__PURE__ */ jsx21(
|
|
19354
|
+
ToolbarAction,
|
|
19355
|
+
{
|
|
19356
|
+
label: gatedLabel("Move right"),
|
|
19357
|
+
onClick: onMoveRight,
|
|
19358
|
+
disabled: !itemEditOn || index >= itemCount - 1,
|
|
19359
|
+
children: /* @__PURE__ */ jsx21(ArrowRight2, { size: 16, style: { pointerEvents: "none" } })
|
|
19360
|
+
}
|
|
19361
|
+
),
|
|
19362
|
+
/* @__PURE__ */ jsx21(ToolbarAction, { label: gatedLabel("Remove image"), onClick: onRemoveItem, disabled: !itemEditOn || itemCount <= 1, children: /* @__PURE__ */ jsx21(ImageMinus, { size: 16, style: { pointerEvents: "none" } }) }),
|
|
19363
|
+
/* @__PURE__ */ jsx21(ToolbarSeparator, {}),
|
|
19364
|
+
/* @__PURE__ */ jsx21(OptionMenu, { label: "Layout", value: variant, options: VARIANTS, onChange: onSetVariant }),
|
|
19365
|
+
/* @__PURE__ */ jsx21(OptionMenu, { label: "Hover", value: hover, options: HOVERS, onChange: onSetHover }),
|
|
19366
|
+
/* @__PURE__ */ jsx21(
|
|
19367
|
+
ToolbarAction,
|
|
19368
|
+
{
|
|
19369
|
+
label: treatment === "grayscale" ? "Show in color" : "Show grayscale",
|
|
19370
|
+
active: treatment === "grayscale",
|
|
19371
|
+
onClick: () => onSetTreatment(treatment === "grayscale" ? "color" : "grayscale"),
|
|
19372
|
+
children: /* @__PURE__ */ jsx21(Palette, { size: 16, style: { pointerEvents: "none" } })
|
|
19373
|
+
}
|
|
19374
|
+
),
|
|
19375
|
+
/* @__PURE__ */ jsx21(ToolbarSeparator, {}),
|
|
19376
|
+
ALIGNS.map(({ value, label, Icon }) => /* @__PURE__ */ jsx21(ToolbarAction, { label, active: align === value, onClick: () => onSetAlign(value), children: /* @__PURE__ */ jsx21(Icon, { size: 16, style: { pointerEvents: "none" } }) }, value)),
|
|
19377
|
+
/* @__PURE__ */ jsx21(ToolbarSeparator, {}),
|
|
19378
|
+
/* @__PURE__ */ jsx21(ToolbarAction, { label: "Smaller", onClick: () => onResize(-8), children: /* @__PURE__ */ jsx21(Minus, { size: 16, style: { pointerEvents: "none" } }) }),
|
|
19379
|
+
/* @__PURE__ */ jsxs12("span", { className: "min-w-[40px] text-center text-xs tabular-nums text-muted-foreground", children: [
|
|
19380
|
+
sizeValue,
|
|
19381
|
+
"px"
|
|
19382
|
+
] }),
|
|
19383
|
+
/* @__PURE__ */ jsx21(ToolbarAction, { label: "Larger", onClick: () => onResize(8), children: /* @__PURE__ */ jsx21(Plus2, { size: 16, style: { pointerEvents: "none" } }) }),
|
|
19384
|
+
/* @__PURE__ */ jsx21(ToolbarSeparator, {}),
|
|
19385
|
+
/* @__PURE__ */ jsx21(ToolbarAction, { label: "Add image", onClick: onAddItem, children: /* @__PURE__ */ jsx21(ImagePlus, { size: 16, style: { pointerEvents: "none" } }) })
|
|
19386
|
+
]
|
|
19387
|
+
}
|
|
19388
|
+
),
|
|
19389
|
+
error && /* @__PURE__ */ jsx21("div", { className: "max-w-[260px] rounded-md bg-background px-2 py-1 text-center text-[11px] text-destructive shadow-sm", children: error })
|
|
19176
19390
|
]
|
|
19177
19391
|
}
|
|
19178
|
-
);
|
|
19392
|
+
) });
|
|
19179
19393
|
}
|
|
19180
19394
|
function findMediaStripSlots(tree) {
|
|
19181
19395
|
const stack = tree.rows.flatMap((row) => row.blocks);
|
|
@@ -19194,31 +19408,23 @@ function AiMediaStripOverlay({
|
|
|
19194
19408
|
}) {
|
|
19195
19409
|
const [hover, setHover] = useState8(null);
|
|
19196
19410
|
const [active, setActive] = useState8(null);
|
|
19411
|
+
const [itemEditOn, setItemEditOn] = useState8(false);
|
|
19412
|
+
const [linkOpen, setLinkOpen] = useState8(false);
|
|
19197
19413
|
const [pending, setPending] = useState8(false);
|
|
19198
19414
|
const [error, setError] = useState8(null);
|
|
19199
19415
|
const activeRef = useRef5(null);
|
|
19200
19416
|
activeRef.current = active;
|
|
19417
|
+
const linkOpenRef = useRef5(false);
|
|
19418
|
+
linkOpenRef.current = linkOpen;
|
|
19201
19419
|
useEffect6(() => {
|
|
19202
19420
|
const onMove = (e) => {
|
|
19421
|
+
const ref = itemRefFromTarget(e.target);
|
|
19203
19422
|
const t = e.target;
|
|
19204
|
-
|
|
19205
|
-
|
|
19206
|
-
|
|
19207
|
-
|
|
19208
|
-
|
|
19209
|
-
if (!itemEl) {
|
|
19210
|
-
setHover(null);
|
|
19211
|
-
return;
|
|
19212
|
-
}
|
|
19213
|
-
const sectionEl = itemEl.closest("[data-ohw-section]");
|
|
19214
|
-
const unit = sectionEl ? movableUnit(sectionEl) : null;
|
|
19215
|
-
const sectionId = unit ? instanceIdOf(unit) || null : null;
|
|
19216
|
-
const index = Number(itemEl.dataset.ohwMediaStripIndex);
|
|
19217
|
-
if (!sectionId || Number.isNaN(index)) {
|
|
19218
|
-
setHover(null);
|
|
19219
|
-
return;
|
|
19220
|
-
}
|
|
19221
|
-
setHover({ sectionId, index });
|
|
19423
|
+
const overEditable = Boolean(t?.closest?.("[data-ohw-editable]"));
|
|
19424
|
+
setHover((prev) => {
|
|
19425
|
+
const next = ref && !overEditable ? ref : null;
|
|
19426
|
+
return sameRef(prev, next) ? prev : next;
|
|
19427
|
+
});
|
|
19222
19428
|
};
|
|
19223
19429
|
const onLeave = () => setHover(null);
|
|
19224
19430
|
document.addEventListener("mousemove", onMove, { passive: true });
|
|
@@ -19230,23 +19436,25 @@ function AiMediaStripOverlay({
|
|
|
19230
19436
|
}, []);
|
|
19231
19437
|
useEffect6(() => {
|
|
19232
19438
|
const onClick = (e) => {
|
|
19233
|
-
const current = activeRef.current;
|
|
19234
|
-
if (!current) return;
|
|
19235
19439
|
const t = e.target;
|
|
19236
|
-
if (!(t instanceof
|
|
19237
|
-
if (t.closest(
|
|
19238
|
-
const
|
|
19239
|
-
if (
|
|
19240
|
-
|
|
19440
|
+
if (!(t instanceof Element)) return;
|
|
19441
|
+
if (t.closest(CHROME_SELECTOR)) return;
|
|
19442
|
+
const ref = itemRefFromTarget(t);
|
|
19443
|
+
if (sameRef(activeRef.current, ref)) return;
|
|
19444
|
+
if (ref) clearInteractionChromeRef.current();
|
|
19445
|
+
setItemEditOn(false);
|
|
19241
19446
|
setError(null);
|
|
19447
|
+
setActive(ref);
|
|
19242
19448
|
};
|
|
19243
19449
|
document.addEventListener("click", onClick, true);
|
|
19244
19450
|
return () => document.removeEventListener("click", onClick, true);
|
|
19245
|
-
}, []);
|
|
19451
|
+
}, [clearInteractionChromeRef]);
|
|
19246
19452
|
useEffect6(() => {
|
|
19247
19453
|
const onBlur = () => {
|
|
19248
19454
|
if (!activeRef.current) return;
|
|
19249
19455
|
setActive(null);
|
|
19456
|
+
setItemEditOn(false);
|
|
19457
|
+
setLinkOpen(false);
|
|
19250
19458
|
setError(null);
|
|
19251
19459
|
};
|
|
19252
19460
|
window.addEventListener("blur", onBlur);
|
|
@@ -19256,7 +19464,10 @@ function AiMediaStripOverlay({
|
|
|
19256
19464
|
const onKeyDown = (e) => {
|
|
19257
19465
|
if (e.key !== "Escape") return;
|
|
19258
19466
|
if (!activeRef.current) return;
|
|
19467
|
+
if (linkOpenRef.current) return;
|
|
19468
|
+
if (document.querySelector('[data-ohw-more-menu][data-state="open"]')) return;
|
|
19259
19469
|
setActive(null);
|
|
19470
|
+
setItemEditOn(false);
|
|
19260
19471
|
setError(null);
|
|
19261
19472
|
};
|
|
19262
19473
|
document.addEventListener("keydown", onKeyDown);
|
|
@@ -19290,137 +19501,133 @@ function AiMediaStripOverlay({
|
|
|
19290
19501
|
tree: nextTree,
|
|
19291
19502
|
label: entry.label,
|
|
19292
19503
|
media: extraMedia ? { ...entry.media, ...extraMedia } : entry.media,
|
|
19293
|
-
...entry.brand ? { brand: entry.brand } : {}
|
|
19504
|
+
...entry.brand ? { brand: entry.brand } : {},
|
|
19505
|
+
// The user is already looking at the strip they just edited — recentering the viewport
|
|
19506
|
+
// on every edit reads as the section jumping around.
|
|
19507
|
+
skipScrollIntoView: true
|
|
19294
19508
|
});
|
|
19295
19509
|
return true;
|
|
19296
19510
|
},
|
|
19297
19511
|
[findEntry, postToParent2, applyTreeLocalRef]
|
|
19298
19512
|
);
|
|
19299
19513
|
const activeEntry = active ? findEntry(active.sectionId) : null;
|
|
19300
|
-
const hoverHandleRect = useLiveItemRect(!active && hover ? hover : null);
|
|
19301
19514
|
const activeItemRect = useLiveItemRect(active);
|
|
19302
|
-
const
|
|
19303
|
-
const
|
|
19304
|
-
|
|
19305
|
-
|
|
19306
|
-
|
|
19307
|
-
|
|
19308
|
-
|
|
19309
|
-
|
|
19310
|
-
|
|
19311
|
-
|
|
19312
|
-
|
|
19313
|
-
|
|
19314
|
-
|
|
19315
|
-
|
|
19316
|
-
|
|
19317
|
-
|
|
19318
|
-
|
|
19319
|
-
|
|
19320
|
-
|
|
19321
|
-
|
|
19322
|
-
|
|
19323
|
-
|
|
19324
|
-
|
|
19325
|
-
|
|
19326
|
-
|
|
19327
|
-
|
|
19328
|
-
|
|
19329
|
-
|
|
19330
|
-
|
|
19331
|
-
|
|
19332
|
-
|
|
19333
|
-
|
|
19334
|
-
|
|
19335
|
-
|
|
19336
|
-
activeItemRect && active && activeEntry && /* @__PURE__ */ jsx20(
|
|
19337
|
-
ItemInteractionLayer,
|
|
19338
|
-
{
|
|
19339
|
-
rect: activeItemRect,
|
|
19340
|
-
state: toolbarState,
|
|
19341
|
-
toolbar: /* @__PURE__ */ jsx20(
|
|
19342
|
-
MediaStripToolbar,
|
|
19343
|
-
{
|
|
19344
|
-
entry: activeEntry,
|
|
19345
|
-
index: active.index,
|
|
19346
|
-
pending,
|
|
19347
|
-
error,
|
|
19348
|
-
onSetVariant: (variant) => runMutation(active.sectionId, (tree) => setMediaStripVariant(tree, variant)),
|
|
19349
|
-
onSetAlign: (align) => runMutation(active.sectionId, (tree) => setMediaStripAlign(tree, align)),
|
|
19350
|
-
onSetHover: (hoverPreset) => runMutation(active.sectionId, (tree) => setMediaStripHover(tree, hoverPreset)),
|
|
19351
|
-
onSetTreatment: (treatment) => runMutation(active.sectionId, (tree) => setMediaStripTreatment(tree, treatment)),
|
|
19352
|
-
onResize: (delta) => {
|
|
19353
|
-
const slots = findMediaStripSlots(activeEntry.tree);
|
|
19354
|
-
const variant = slots?.variant === "reel" ? "reel" : "logos";
|
|
19355
|
-
const current = variant === "logos" ? typeof slots?.logoMaxHeight === "number" ? slots.logoMaxHeight : 48 : typeof slots?.cardWidth === "number" ? slots.cardWidth : 240;
|
|
19356
|
-
void runMutation(active.sectionId, (tree) => setMediaStripSizing(tree, current + delta));
|
|
19357
|
-
},
|
|
19358
|
-
onSetAlt: (alt) => {
|
|
19359
|
-
void runMutation(active.sectionId, (tree) => setMediaStripItemAlt(tree, active.index, alt));
|
|
19360
|
-
},
|
|
19361
|
-
onSetLink: (href, linkTarget) => {
|
|
19515
|
+
const activeStripRect = useLiveItemRect(active, true);
|
|
19516
|
+
const hoverRect = useLiveItemRect(hover && !sameRef(hover, active) ? hover : null);
|
|
19517
|
+
const activeItems = activeEntry ? mediaStripItems(activeEntry.tree) : [];
|
|
19518
|
+
const activeItem = active ? activeItems[active.index] : void 0;
|
|
19519
|
+
const activeHref = activeItem?.href ?? "";
|
|
19520
|
+
const activeTarget = activeItem?.linkTarget === "same-tab" ? "same-tab" : "new-tab";
|
|
19521
|
+
return /* @__PURE__ */ jsxs12(Fragment7, { children: [
|
|
19522
|
+
hoverRect && /* @__PURE__ */ jsx21(ItemInteractionLayer, { rect: hoverRect, state: "hover" }),
|
|
19523
|
+
activeItemRect && activeStripRect && active && activeEntry && /* @__PURE__ */ jsxs12(Fragment7, { children: [
|
|
19524
|
+
/* @__PURE__ */ jsx21(ItemInteractionLayer, { rect: activeItemRect, state: "active-top" }),
|
|
19525
|
+
/* @__PURE__ */ jsx21(StripToolbarSlot, { stripRect: activeStripRect, children: /* @__PURE__ */ jsx21(
|
|
19526
|
+
MediaStripToolbar,
|
|
19527
|
+
{
|
|
19528
|
+
entry: activeEntry,
|
|
19529
|
+
index: active.index,
|
|
19530
|
+
pending,
|
|
19531
|
+
error,
|
|
19532
|
+
itemEditOn,
|
|
19533
|
+
onToggleItemEdit: () => setItemEditOn((on) => !on),
|
|
19534
|
+
onSetVariant: (variant) => runMutation(active.sectionId, (tree) => setMediaStripVariant(tree, variant)),
|
|
19535
|
+
onSetAlign: (align) => runMutation(active.sectionId, (tree) => setMediaStripAlign(tree, align)),
|
|
19536
|
+
onSetHover: (hoverPreset) => runMutation(active.sectionId, (tree) => setMediaStripHover(tree, hoverPreset)),
|
|
19537
|
+
onSetTreatment: (treatment) => runMutation(active.sectionId, (tree) => setMediaStripTreatment(tree, treatment)),
|
|
19538
|
+
onResize: (delta) => {
|
|
19539
|
+
const slots = findMediaStripSlots(activeEntry.tree);
|
|
19540
|
+
const variant = slots?.variant === "reel" ? "reel" : "logos";
|
|
19541
|
+
const current = variant === "logos" ? typeof slots?.logoMaxHeight === "number" ? slots.logoMaxHeight : 48 : typeof slots?.cardWidth === "number" ? slots.cardWidth : 240;
|
|
19542
|
+
void runMutation(active.sectionId, (tree) => setMediaStripSizing(tree, current + delta));
|
|
19543
|
+
},
|
|
19544
|
+
onOpenLink: () => setLinkOpen(true),
|
|
19545
|
+
onAddItem: () => {
|
|
19546
|
+
void requestAssetPick(postToParent2).then((picked) => {
|
|
19547
|
+
if (!picked) return;
|
|
19548
|
+
const item = { assetId: picked.assetId, alt: "Logo" };
|
|
19362
19549
|
void runMutation(
|
|
19363
19550
|
active.sectionId,
|
|
19364
|
-
(tree) =>
|
|
19365
|
-
|
|
19366
|
-
|
|
19367
|
-
|
|
19368
|
-
void requestAssetPick(postToParent2).then((picked) => {
|
|
19369
|
-
if (!picked) return;
|
|
19370
|
-
const item = { assetId: picked.assetId, alt: "Logo" };
|
|
19371
|
-
void runMutation(
|
|
19372
|
-
active.sectionId,
|
|
19373
|
-
(tree) => addMediaStripItem(tree, item, active.index),
|
|
19374
|
-
{ [picked.assetId]: picked.url }
|
|
19375
|
-
).then((applied) => {
|
|
19376
|
-
if (applied) setActive({ sectionId: active.sectionId, index: active.index + 1 });
|
|
19377
|
-
});
|
|
19551
|
+
(tree) => addMediaStripItem(tree, item, active.index),
|
|
19552
|
+
{ [picked.assetId]: picked.url }
|
|
19553
|
+
).then((applied) => {
|
|
19554
|
+
if (applied) setActive({ sectionId: active.sectionId, index: active.index + 1 });
|
|
19378
19555
|
});
|
|
19379
|
-
}
|
|
19380
|
-
|
|
19381
|
-
|
|
19382
|
-
|
|
19383
|
-
|
|
19384
|
-
|
|
19385
|
-
|
|
19386
|
-
|
|
19387
|
-
|
|
19388
|
-
});
|
|
19389
|
-
},
|
|
19390
|
-
onRemoveItem: () => {
|
|
19391
|
-
void runMutation(active.sectionId, (tree) => removeMediaStripItem(tree, active.index)).then(
|
|
19392
|
-
(applied) => {
|
|
19393
|
-
if (applied) setActive(null);
|
|
19394
|
-
}
|
|
19395
|
-
);
|
|
19396
|
-
},
|
|
19397
|
-
onMoveLeft: () => {
|
|
19398
|
-
void runMutation(active.sectionId, (tree) => reorderMediaStripItem(tree, active.index, -1)).then(
|
|
19399
|
-
(applied) => {
|
|
19400
|
-
if (applied) setActive({ sectionId: active.sectionId, index: active.index - 1 });
|
|
19401
|
-
}
|
|
19402
|
-
);
|
|
19403
|
-
},
|
|
19404
|
-
onMoveRight: () => {
|
|
19405
|
-
void runMutation(active.sectionId, (tree) => reorderMediaStripItem(tree, active.index, 1)).then(
|
|
19406
|
-
(applied) => {
|
|
19407
|
-
if (applied) setActive({ sectionId: active.sectionId, index: active.index + 1 });
|
|
19408
|
-
}
|
|
19556
|
+
});
|
|
19557
|
+
},
|
|
19558
|
+
onChangeImage: () => {
|
|
19559
|
+
void requestAssetPick(postToParent2).then((picked) => {
|
|
19560
|
+
if (!picked) return;
|
|
19561
|
+
void runMutation(
|
|
19562
|
+
active.sectionId,
|
|
19563
|
+
(tree) => setMediaStripItemAsset(tree, active.index, picked.assetId),
|
|
19564
|
+
{ [picked.assetId]: picked.url }
|
|
19409
19565
|
);
|
|
19410
|
-
}
|
|
19566
|
+
});
|
|
19567
|
+
},
|
|
19568
|
+
onRemoveItem: () => {
|
|
19569
|
+
void runMutation(active.sectionId, (tree) => removeMediaStripItem(tree, active.index)).then(
|
|
19570
|
+
(applied) => {
|
|
19571
|
+
if (applied) setActive(null);
|
|
19572
|
+
}
|
|
19573
|
+
);
|
|
19574
|
+
},
|
|
19575
|
+
onMoveLeft: () => {
|
|
19576
|
+
void runMutation(active.sectionId, (tree) => reorderMediaStripItem(tree, active.index, -1)).then(
|
|
19577
|
+
(applied) => {
|
|
19578
|
+
if (applied) setActive({ sectionId: active.sectionId, index: active.index - 1 });
|
|
19579
|
+
}
|
|
19580
|
+
);
|
|
19581
|
+
},
|
|
19582
|
+
onMoveRight: () => {
|
|
19583
|
+
void runMutation(active.sectionId, (tree) => reorderMediaStripItem(tree, active.index, 1)).then(
|
|
19584
|
+
(applied) => {
|
|
19585
|
+
if (applied) setActive({ sectionId: active.sectionId, index: active.index + 1 });
|
|
19586
|
+
}
|
|
19587
|
+
);
|
|
19411
19588
|
}
|
|
19412
|
-
|
|
19413
|
-
}
|
|
19414
|
-
|
|
19589
|
+
}
|
|
19590
|
+
) }),
|
|
19591
|
+
/* @__PURE__ */ jsx21(
|
|
19592
|
+
"div",
|
|
19593
|
+
{
|
|
19594
|
+
"data-ohw-bridge": "",
|
|
19595
|
+
"data-ohw-item-interaction": "",
|
|
19596
|
+
"aria-hidden": true,
|
|
19597
|
+
className: "pointer-events-none fixed rounded-[4px] px-[7px] py-[3px] font-sans text-[11px] font-medium leading-none text-primary-foreground whitespace-nowrap",
|
|
19598
|
+
style: {
|
|
19599
|
+
top: activeItemRect.top + activeItemRect.height + 10,
|
|
19600
|
+
left: activeItemRect.left - 5,
|
|
19601
|
+
background: PRIMARY3,
|
|
19602
|
+
zIndex: 2147483644
|
|
19603
|
+
},
|
|
19604
|
+
children: "Media item"
|
|
19605
|
+
}
|
|
19606
|
+
),
|
|
19607
|
+
linkOpen && /* @__PURE__ */ jsx21(
|
|
19608
|
+
LinkModal,
|
|
19609
|
+
{
|
|
19610
|
+
href: activeHref,
|
|
19611
|
+
linkTarget: activeTarget,
|
|
19612
|
+
onClose: () => setLinkOpen(false),
|
|
19613
|
+
onSave: (href, linkTarget) => {
|
|
19614
|
+
void runMutation(
|
|
19615
|
+
active.sectionId,
|
|
19616
|
+
(tree) => setMediaStripItemLink(tree, active.index, href ? { href, linkTarget } : {})
|
|
19617
|
+
);
|
|
19618
|
+
}
|
|
19619
|
+
}
|
|
19620
|
+
)
|
|
19621
|
+
] })
|
|
19415
19622
|
] });
|
|
19416
19623
|
}
|
|
19417
19624
|
|
|
19418
19625
|
// src/ui/ai-section/AiPricingCardOverlay.tsx
|
|
19419
|
-
import { useCallback as useCallback4, useEffect as useEffect7, useLayoutEffect as
|
|
19420
|
-
import { Check as
|
|
19421
|
-
import { Fragment as Fragment8, jsx as
|
|
19626
|
+
import { useCallback as useCallback4, useEffect as useEffect7, useLayoutEffect as useLayoutEffect5, useRef as useRef6, useState as useState9 } from "react";
|
|
19627
|
+
import { Check as Check3, ChevronDown as ChevronDown4, Minus as Minus2, Plus as Plus3, Star as Star2 } from "lucide-react";
|
|
19628
|
+
import { Fragment as Fragment8, jsx as jsx22, jsxs as jsxs13 } from "react/jsx-runtime";
|
|
19422
19629
|
var PRIMARY4 = "var(--ohw-primary, #0885FE)";
|
|
19423
|
-
var
|
|
19630
|
+
var CHROME_SELECTOR2 = "[data-ohw-toolbar], [data-ohw-edit-chrome], [data-ohw-item-interaction], [data-ohw-link-modal-root], [data-ohw-section-picker], [data-ohw-ai-review], [data-ohw-more-menu]";
|
|
19424
19631
|
function findPricingCardElement(sectionId, index) {
|
|
19425
19632
|
const sectionEl = findByInstanceId(sectionId);
|
|
19426
19633
|
if (!sectionEl) return null;
|
|
@@ -19432,7 +19639,7 @@ function findPricingCardElement(sectionId, index) {
|
|
|
19432
19639
|
}
|
|
19433
19640
|
function cardRefFromTarget(target) {
|
|
19434
19641
|
if (!(target instanceof Element)) return null;
|
|
19435
|
-
if (target.closest(
|
|
19642
|
+
if (target.closest(CHROME_SELECTOR2)) return null;
|
|
19436
19643
|
const cardEl = target.closest("[data-ohw-pricing-card]");
|
|
19437
19644
|
if (!cardEl) return null;
|
|
19438
19645
|
const sectionEl = cardEl.closest("[data-ohw-section]");
|
|
@@ -19442,21 +19649,21 @@ function cardRefFromTarget(target) {
|
|
|
19442
19649
|
if (!sectionId || Number.isNaN(index)) return null;
|
|
19443
19650
|
return { sectionId, index };
|
|
19444
19651
|
}
|
|
19445
|
-
function
|
|
19652
|
+
function sameRef2(a, b) {
|
|
19446
19653
|
return a?.sectionId === b?.sectionId && a?.index === b?.index;
|
|
19447
19654
|
}
|
|
19448
|
-
function
|
|
19655
|
+
function rectOf2(el) {
|
|
19449
19656
|
if (!el) return null;
|
|
19450
19657
|
const r2 = el.getBoundingClientRect();
|
|
19451
19658
|
if (r2.width <= 0 || r2.height <= 0) return null;
|
|
19452
19659
|
return { top: r2.top, left: r2.left, width: r2.width, height: r2.height };
|
|
19453
19660
|
}
|
|
19454
19661
|
function readRect3(ref) {
|
|
19455
|
-
return
|
|
19662
|
+
return rectOf2(ref && findPricingCardElement(ref.sectionId, ref.index));
|
|
19456
19663
|
}
|
|
19457
19664
|
function readGridRect(ref) {
|
|
19458
19665
|
const card = ref && findPricingCardElement(ref.sectionId, ref.index);
|
|
19459
|
-
return
|
|
19666
|
+
return rectOf2(card?.closest("[data-ohw-pricing-collection]") ?? card);
|
|
19460
19667
|
}
|
|
19461
19668
|
function useLiveCardRect(ref, grid = false) {
|
|
19462
19669
|
const [rect, setRect] = useState9(null);
|
|
@@ -19486,19 +19693,19 @@ function useLiveCardRect(ref, grid = false) {
|
|
|
19486
19693
|
}
|
|
19487
19694
|
var TOOLBAR_GRID_GAP = 52;
|
|
19488
19695
|
var TOOLBAR_GRID_GAP_MOBILE = 42;
|
|
19489
|
-
var
|
|
19696
|
+
var TOOLBAR_EDGE_MARGIN3 = 4;
|
|
19490
19697
|
function GridToolbarSlot({ gridRect, children }) {
|
|
19491
19698
|
const slotRef = useRef6(null);
|
|
19492
19699
|
const [shift, setShift] = useState9(0);
|
|
19493
19700
|
const centerX = gridRect.left + gridRect.width / 2;
|
|
19494
|
-
|
|
19701
|
+
useLayoutEffect5(() => {
|
|
19495
19702
|
const slot = slotRef.current;
|
|
19496
19703
|
if (!slot) return;
|
|
19497
19704
|
const clamp = () => {
|
|
19498
19705
|
const w = slot.offsetWidth;
|
|
19499
19706
|
if (w <= 0) return;
|
|
19500
19707
|
const half = w / 2;
|
|
19501
|
-
const clamped = Math.max(
|
|
19708
|
+
const clamped = Math.max(TOOLBAR_EDGE_MARGIN3 + half, Math.min(centerX, window.innerWidth - TOOLBAR_EDGE_MARGIN3 - half));
|
|
19502
19709
|
setShift((prev) => Math.abs(prev - (clamped - centerX)) < 0.5 ? prev : clamped - centerX);
|
|
19503
19710
|
};
|
|
19504
19711
|
clamp();
|
|
@@ -19507,7 +19714,7 @@ function GridToolbarSlot({ gridRect, children }) {
|
|
|
19507
19714
|
return () => ro.disconnect();
|
|
19508
19715
|
}, [centerX, children]);
|
|
19509
19716
|
const mobile = window.innerWidth <= 480;
|
|
19510
|
-
return /* @__PURE__ */
|
|
19717
|
+
return /* @__PURE__ */ jsx22(
|
|
19511
19718
|
"div",
|
|
19512
19719
|
{
|
|
19513
19720
|
ref: slotRef,
|
|
@@ -19542,7 +19749,7 @@ function requestValidateTree2(postToParent2, tree) {
|
|
|
19542
19749
|
});
|
|
19543
19750
|
}
|
|
19544
19751
|
function StyleSwatch({ style }) {
|
|
19545
|
-
return /* @__PURE__ */
|
|
19752
|
+
return /* @__PURE__ */ jsx22(
|
|
19546
19753
|
"span",
|
|
19547
19754
|
{
|
|
19548
19755
|
"aria-hidden": true,
|
|
@@ -19556,35 +19763,35 @@ function StyleSwatch({ style }) {
|
|
|
19556
19763
|
);
|
|
19557
19764
|
}
|
|
19558
19765
|
function ButtonGlyph() {
|
|
19559
|
-
return /* @__PURE__ */
|
|
19560
|
-
/* @__PURE__ */
|
|
19561
|
-
/* @__PURE__ */
|
|
19766
|
+
return /* @__PURE__ */ jsxs13("svg", { width: "18", height: "12", viewBox: "0 0 18 12", fill: "none", "aria-hidden": true, style: { pointerEvents: "none" }, children: [
|
|
19767
|
+
/* @__PURE__ */ jsx22("rect", { x: "0.75", y: "0.75", width: "16.5", height: "10.5", rx: "3", stroke: "currentColor", strokeWidth: "1.5" }),
|
|
19768
|
+
/* @__PURE__ */ jsx22("path", { d: "M5.5 6H12.5", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round" })
|
|
19562
19769
|
] });
|
|
19563
19770
|
}
|
|
19564
19771
|
function FeatureGlyph({ mode }) {
|
|
19565
|
-
return /* @__PURE__ */
|
|
19566
|
-
/* @__PURE__ */
|
|
19567
|
-
/* @__PURE__ */
|
|
19568
|
-
/* @__PURE__ */
|
|
19569
|
-
/* @__PURE__ */
|
|
19570
|
-
/* @__PURE__ */
|
|
19571
|
-
mode === "add" && /* @__PURE__ */
|
|
19772
|
+
return /* @__PURE__ */ jsxs13("svg", { width: "18", height: "18", viewBox: "0 0 18 18", fill: "none", "aria-hidden": true, style: { pointerEvents: "none" }, children: [
|
|
19773
|
+
/* @__PURE__ */ jsx22("circle", { cx: "8", cy: "8", r: "7.25", stroke: "currentColor", strokeWidth: "1.5" }),
|
|
19774
|
+
/* @__PURE__ */ jsx22("path", { d: "M5 8.2L7.2 10.3L11 6", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round" }),
|
|
19775
|
+
/* @__PURE__ */ jsx22("circle", { cx: "13.5", cy: "13.5", r: "4.25", fill: "var(--ohw-background, #ffffff)", stroke: "var(--ohw-background, #ffffff)", strokeWidth: "1" }),
|
|
19776
|
+
/* @__PURE__ */ jsx22("circle", { cx: "13.5", cy: "13.5", r: "3.75", fill: "var(--ohw-background, #ffffff)", stroke: PRIMARY4, strokeWidth: "1" }),
|
|
19777
|
+
/* @__PURE__ */ jsx22("path", { d: "M11.5 13.5H15.5", stroke: PRIMARY4, strokeWidth: "1.5", strokeLinecap: "round" }),
|
|
19778
|
+
mode === "add" && /* @__PURE__ */ jsx22("path", { d: "M13.5 11.5V15.5", stroke: PRIMARY4, strokeWidth: "1.5", strokeLinecap: "round" })
|
|
19572
19779
|
] });
|
|
19573
19780
|
}
|
|
19574
|
-
function
|
|
19781
|
+
function ToolbarAction2({
|
|
19575
19782
|
label,
|
|
19576
19783
|
onClick,
|
|
19577
19784
|
disabled = false,
|
|
19578
19785
|
children
|
|
19579
19786
|
}) {
|
|
19580
|
-
const button = /* @__PURE__ */
|
|
19581
|
-
return /* @__PURE__ */
|
|
19582
|
-
/* @__PURE__ */
|
|
19583
|
-
/* @__PURE__ */
|
|
19787
|
+
const button = /* @__PURE__ */ jsx22(CustomToolbarButton, { type: "button", "aria-label": label, disabled, onClick, className: "size-8", children });
|
|
19788
|
+
return /* @__PURE__ */ jsxs13(Tooltip, { children: [
|
|
19789
|
+
/* @__PURE__ */ jsx22(TooltipTrigger, { asChild: true, children: disabled ? /* @__PURE__ */ jsx22("span", { className: "inline-flex", children: button }) : button }),
|
|
19790
|
+
/* @__PURE__ */ jsx22(TooltipContent, { side: "bottom", sideOffset: 8, children: label })
|
|
19584
19791
|
] });
|
|
19585
19792
|
}
|
|
19586
|
-
function
|
|
19587
|
-
return /* @__PURE__ */
|
|
19793
|
+
function ToolbarSeparator2() {
|
|
19794
|
+
return /* @__PURE__ */ jsx22("span", { "aria-hidden": true, className: "mx-0.5 block h-6 w-px shrink-0 bg-border" });
|
|
19588
19795
|
}
|
|
19589
19796
|
function CardStyleMenu({
|
|
19590
19797
|
value,
|
|
@@ -19592,7 +19799,7 @@ function CardStyleMenu({
|
|
|
19592
19799
|
disabled = false
|
|
19593
19800
|
}) {
|
|
19594
19801
|
const current = PRICING_CARD_STYLES.find((s) => s.value === value) ?? PRICING_CARD_STYLES[0];
|
|
19595
|
-
const trigger = /* @__PURE__ */
|
|
19802
|
+
const trigger = /* @__PURE__ */ jsxs13(
|
|
19596
19803
|
"button",
|
|
19597
19804
|
{
|
|
19598
19805
|
type: "button",
|
|
@@ -19603,28 +19810,28 @@ function CardStyleMenu({
|
|
|
19603
19810
|
disabled && "cursor-not-allowed opacity-40 hover:bg-transparent"
|
|
19604
19811
|
),
|
|
19605
19812
|
children: [
|
|
19606
|
-
/* @__PURE__ */
|
|
19607
|
-
/* @__PURE__ */
|
|
19608
|
-
/* @__PURE__ */
|
|
19813
|
+
/* @__PURE__ */ jsx22(StyleSwatch, { style: current.value }),
|
|
19814
|
+
/* @__PURE__ */ jsx22("span", { className: "flex-1 text-left", children: current.label }),
|
|
19815
|
+
/* @__PURE__ */ jsx22(ChevronDown4, { size: 16, style: { pointerEvents: "none" } })
|
|
19609
19816
|
]
|
|
19610
19817
|
}
|
|
19611
19818
|
);
|
|
19612
19819
|
if (disabled) {
|
|
19613
|
-
return /* @__PURE__ */
|
|
19614
|
-
/* @__PURE__ */
|
|
19615
|
-
/* @__PURE__ */
|
|
19616
|
-
/* @__PURE__ */
|
|
19617
|
-
/* @__PURE__ */
|
|
19820
|
+
return /* @__PURE__ */ jsxs13("div", { className: "flex items-center gap-1.5 pl-1.5", children: [
|
|
19821
|
+
/* @__PURE__ */ jsx22("span", { className: "text-xs text-muted-foreground opacity-50", children: "Card style" }),
|
|
19822
|
+
/* @__PURE__ */ jsxs13(Tooltip, { children: [
|
|
19823
|
+
/* @__PURE__ */ jsx22(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsx22("span", { className: "inline-flex", children: trigger }) }),
|
|
19824
|
+
/* @__PURE__ */ jsx22(TooltipContent, { side: "bottom", sideOffset: 8, children: "Mark as featured to edit card style" })
|
|
19618
19825
|
] })
|
|
19619
19826
|
] });
|
|
19620
19827
|
}
|
|
19621
|
-
return /* @__PURE__ */
|
|
19622
|
-
/* @__PURE__ */
|
|
19623
|
-
/* @__PURE__ */
|
|
19624
|
-
/* @__PURE__ */
|
|
19625
|
-
/* @__PURE__ */
|
|
19828
|
+
return /* @__PURE__ */ jsxs13("div", { className: "flex items-center gap-1.5 pl-1.5", children: [
|
|
19829
|
+
/* @__PURE__ */ jsx22("span", { className: "text-xs text-muted-foreground", children: "Card style" }),
|
|
19830
|
+
/* @__PURE__ */ jsxs13(DropdownMenu, { modal: false, children: [
|
|
19831
|
+
/* @__PURE__ */ jsx22(DropdownMenuTrigger, { asChild: true, children: trigger }),
|
|
19832
|
+
/* @__PURE__ */ jsx22(DropdownMenuContent, { align: "end", sideOffset: 8, className: "w-[152px] min-w-[152px] p-1", children: PRICING_CARD_STYLES.map((style) => {
|
|
19626
19833
|
const selected = style.value === value;
|
|
19627
|
-
return /* @__PURE__ */
|
|
19834
|
+
return /* @__PURE__ */ jsxs13(
|
|
19628
19835
|
DropdownMenuItem,
|
|
19629
19836
|
{
|
|
19630
19837
|
role: "menuitemradio",
|
|
@@ -19632,9 +19839,9 @@ function CardStyleMenu({
|
|
|
19632
19839
|
onSelect: () => onChange(style.value),
|
|
19633
19840
|
className: cn("grid grid-cols-[18px_1fr_16px] gap-2 py-2 pl-2 pr-2 text-[13px]", selected && "bg-muted"),
|
|
19634
19841
|
children: [
|
|
19635
|
-
/* @__PURE__ */
|
|
19636
|
-
/* @__PURE__ */
|
|
19637
|
-
selected && /* @__PURE__ */
|
|
19842
|
+
/* @__PURE__ */ jsx22(StyleSwatch, { style: style.value }),
|
|
19843
|
+
/* @__PURE__ */ jsx22("span", { children: style.label }),
|
|
19844
|
+
selected && /* @__PURE__ */ jsx22(Check3, { size: 16, className: "text-bridge-primary" })
|
|
19638
19845
|
]
|
|
19639
19846
|
},
|
|
19640
19847
|
style.value
|
|
@@ -19664,7 +19871,7 @@ function PricingCardToolbar({
|
|
|
19664
19871
|
const style = pricingCardStyle(entry.tree, index);
|
|
19665
19872
|
const featuredTag = pricingCardFeaturedTag(entry.tree, index);
|
|
19666
19873
|
const mobile = window.innerWidth <= 480;
|
|
19667
|
-
return /* @__PURE__ */
|
|
19874
|
+
return /* @__PURE__ */ jsx22(TooltipProvider, { delayDuration: 0, children: /* @__PURE__ */ jsxs13(
|
|
19668
19875
|
"div",
|
|
19669
19876
|
{
|
|
19670
19877
|
"data-ohw-bridge": "",
|
|
@@ -19676,7 +19883,7 @@ function PricingCardToolbar({
|
|
|
19676
19883
|
),
|
|
19677
19884
|
style: { maxWidth: mobile ? "calc(100vw - 24px)" : void 0 },
|
|
19678
19885
|
children: [
|
|
19679
|
-
/* @__PURE__ */
|
|
19886
|
+
/* @__PURE__ */ jsxs13(
|
|
19680
19887
|
"div",
|
|
19681
19888
|
{
|
|
19682
19889
|
className: cn(
|
|
@@ -19684,9 +19891,9 @@ function PricingCardToolbar({
|
|
|
19684
19891
|
"shadow-[0px_10px_15px_-3px_rgba(0,0,0,0.1),0px_4px_6px_-4px_rgba(0,0,0,0.1)]",
|
|
19685
19892
|
mobile ? "flex-wrap justify-center" : "flex-nowrap"
|
|
19686
19893
|
),
|
|
19687
|
-
children: [
|
|
19688
|
-
/* @__PURE__ */
|
|
19689
|
-
/* @__PURE__ */
|
|
19894
|
+
children: [
|
|
19895
|
+
/* @__PURE__ */ jsxs13(Tooltip, { children: [
|
|
19896
|
+
/* @__PURE__ */ jsx22(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsx22(
|
|
19690
19897
|
CustomToolbarButton,
|
|
19691
19898
|
{
|
|
19692
19899
|
type: "button",
|
|
@@ -19694,7 +19901,7 @@ function PricingCardToolbar({
|
|
|
19694
19901
|
"aria-pressed": featuredTag,
|
|
19695
19902
|
onClick: () => onSetFeaturedTag(!featuredTag),
|
|
19696
19903
|
className: "group size-8",
|
|
19697
|
-
children: /* @__PURE__ */
|
|
19904
|
+
children: /* @__PURE__ */ jsx22(
|
|
19698
19905
|
Star2,
|
|
19699
19906
|
{
|
|
19700
19907
|
size: 16,
|
|
@@ -19709,25 +19916,25 @@ function PricingCardToolbar({
|
|
|
19709
19916
|
)
|
|
19710
19917
|
}
|
|
19711
19918
|
) }),
|
|
19712
|
-
/* @__PURE__ */
|
|
19919
|
+
/* @__PURE__ */ jsx22(TooltipContent, { side: "bottom", sideOffset: 8, children: featuredTag ? "Unmark featured" : "Mark as featured" })
|
|
19713
19920
|
] }),
|
|
19714
|
-
/* @__PURE__ */
|
|
19715
|
-
/* @__PURE__ */
|
|
19716
|
-
/* @__PURE__ */
|
|
19717
|
-
/* @__PURE__ */
|
|
19718
|
-
/* @__PURE__ */
|
|
19719
|
-
/* @__PURE__ */
|
|
19720
|
-
/* @__PURE__ */
|
|
19921
|
+
/* @__PURE__ */ jsx22(ToolbarSeparator2, {}),
|
|
19922
|
+
/* @__PURE__ */ jsx22(CardStyleMenu, { value: style, onChange: onSetStyle, disabled: !featuredTag }),
|
|
19923
|
+
/* @__PURE__ */ jsx22(ToolbarSeparator2, {}),
|
|
19924
|
+
/* @__PURE__ */ jsx22(ToolbarAction2, { label: "Add button", onClick: onAddButton, disabled: buttonCount >= 2, children: /* @__PURE__ */ jsx22(ButtonGlyph, {}) }),
|
|
19925
|
+
/* @__PURE__ */ jsx22(ToolbarAction2, { label: "Remove button", onClick: onRemoveButton, disabled: buttonCount === 0, children: /* @__PURE__ */ jsxs13("span", { className: "relative inline-flex", children: [
|
|
19926
|
+
/* @__PURE__ */ jsx22(ButtonGlyph, {}),
|
|
19927
|
+
/* @__PURE__ */ jsx22(Minus2, { size: 10, strokeWidth: 2.5, className: "absolute -right-1.5 -top-1.5 rounded-full bg-background text-bridge-primary" })
|
|
19721
19928
|
] }) }),
|
|
19722
|
-
/* @__PURE__ */
|
|
19723
|
-
/* @__PURE__ */
|
|
19724
|
-
/* @__PURE__ */
|
|
19725
|
-
/* @__PURE__ */
|
|
19726
|
-
/* @__PURE__ */
|
|
19929
|
+
/* @__PURE__ */ jsx22(ToolbarAction2, { label: "Add feature", onClick: onAddFeature, disabled: featureCount >= 10, children: /* @__PURE__ */ jsx22(FeatureGlyph, { mode: "add" }) }),
|
|
19930
|
+
/* @__PURE__ */ jsx22(ToolbarAction2, { label: "Remove feature", onClick: onRemoveFeature, disabled: featureCount <= 1, children: /* @__PURE__ */ jsx22(FeatureGlyph, { mode: "remove" }) }),
|
|
19931
|
+
/* @__PURE__ */ jsx22(ToolbarSeparator2, {}),
|
|
19932
|
+
/* @__PURE__ */ jsx22(ToolbarAction2, { label: "Add tier", onClick: onAddTier, disabled: collectionCount >= 4, children: /* @__PURE__ */ jsx22(Plus3, { size: 16, style: { pointerEvents: "none" } }) }),
|
|
19933
|
+
/* @__PURE__ */ jsx22(ToolbarAction2, { label: "Remove tier", onClick: onRemoveTier, disabled: collectionCount <= 1, children: /* @__PURE__ */ jsx22(Minus2, { size: 16, style: { pointerEvents: "none" } }) })
|
|
19727
19934
|
]
|
|
19728
19935
|
}
|
|
19729
19936
|
),
|
|
19730
|
-
error && /* @__PURE__ */
|
|
19937
|
+
error && /* @__PURE__ */ jsx22("div", { className: "max-w-[260px] rounded-md bg-background px-2 py-1 text-center text-[11px] text-destructive shadow-sm", children: error })
|
|
19731
19938
|
]
|
|
19732
19939
|
}
|
|
19733
19940
|
) });
|
|
@@ -19761,7 +19968,7 @@ function AiPricingCardOverlay({
|
|
|
19761
19968
|
const overEditable = Boolean(t?.closest?.("[data-ohw-editable], [data-ohw-role], a, button"));
|
|
19762
19969
|
setHover((prev) => {
|
|
19763
19970
|
const next = ref && !overEditable ? ref : null;
|
|
19764
|
-
return
|
|
19971
|
+
return sameRef2(prev, next) ? prev : next;
|
|
19765
19972
|
});
|
|
19766
19973
|
};
|
|
19767
19974
|
const onLeave = () => setHover(null);
|
|
@@ -19776,10 +19983,10 @@ function AiPricingCardOverlay({
|
|
|
19776
19983
|
const onClick = (e) => {
|
|
19777
19984
|
const t = e.target;
|
|
19778
19985
|
if (!(t instanceof Element)) return;
|
|
19779
|
-
if (t.closest(
|
|
19986
|
+
if (t.closest(CHROME_SELECTOR2)) return;
|
|
19780
19987
|
const ref = cardRefFromTarget(t);
|
|
19781
|
-
setActive((prev) =>
|
|
19782
|
-
if (!ref || !
|
|
19988
|
+
setActive((prev) => sameRef2(prev, ref) ? prev : ref);
|
|
19989
|
+
if (!ref || !sameRef2(activeRef.current, ref)) setError(null);
|
|
19783
19990
|
};
|
|
19784
19991
|
document.addEventListener("click", onClick, true);
|
|
19785
19992
|
return () => document.removeEventListener("click", onClick, true);
|
|
@@ -19844,12 +20051,12 @@ function AiPricingCardOverlay({
|
|
|
19844
20051
|
const activeEntry = active ? findEntry(active.sectionId) : null;
|
|
19845
20052
|
const activeCardRect = useLiveCardRect(active);
|
|
19846
20053
|
const activeGridRect = useLiveCardRect(active, true);
|
|
19847
|
-
const hoverRect = useLiveCardRect(hover && !
|
|
19848
|
-
return /* @__PURE__ */
|
|
19849
|
-
hoverRect && /* @__PURE__ */
|
|
19850
|
-
activeCardRect && activeGridRect && active && activeEntry && /* @__PURE__ */
|
|
19851
|
-
/* @__PURE__ */
|
|
19852
|
-
/* @__PURE__ */
|
|
20054
|
+
const hoverRect = useLiveCardRect(hover && !sameRef2(hover, active) ? hover : null);
|
|
20055
|
+
return /* @__PURE__ */ jsxs13(Fragment8, { children: [
|
|
20056
|
+
hoverRect && /* @__PURE__ */ jsx22(ItemInteractionLayer, { rect: hoverRect, state: "hover" }),
|
|
20057
|
+
activeCardRect && activeGridRect && active && activeEntry && /* @__PURE__ */ jsxs13(Fragment8, { children: [
|
|
20058
|
+
/* @__PURE__ */ jsx22(ItemInteractionLayer, { rect: activeCardRect, state: "active-top" }),
|
|
20059
|
+
/* @__PURE__ */ jsx22(GridToolbarSlot, { gridRect: activeGridRect, children: /* @__PURE__ */ jsx22(
|
|
19853
20060
|
PricingCardToolbar,
|
|
19854
20061
|
{
|
|
19855
20062
|
entry: activeEntry,
|
|
@@ -19877,7 +20084,7 @@ function AiPricingCardOverlay({
|
|
|
19877
20084
|
onRemoveFeature: () => runMutation(active.sectionId, (tree) => removePricingCardFeature(tree, active.index))
|
|
19878
20085
|
}
|
|
19879
20086
|
) }),
|
|
19880
|
-
/* @__PURE__ */
|
|
20087
|
+
/* @__PURE__ */ jsx22(
|
|
19881
20088
|
"div",
|
|
19882
20089
|
{
|
|
19883
20090
|
"data-ohw-bridge": "",
|
|
@@ -19970,10 +20177,10 @@ function extractYouTubeId(input) {
|
|
|
19970
20177
|
}
|
|
19971
20178
|
|
|
19972
20179
|
// src/ui/ai-section/AiVideoOverlay.tsx
|
|
19973
|
-
import { Fragment as Fragment9, jsx as
|
|
20180
|
+
import { Fragment as Fragment9, jsx as jsx23, jsxs as jsxs14 } from "react/jsx-runtime";
|
|
19974
20181
|
var PRIMARY5 = "#0885FE";
|
|
19975
|
-
var
|
|
19976
|
-
var
|
|
20182
|
+
var OHW_BLUE = `var(--ohw-primary, ${PRIMARY5})`;
|
|
20183
|
+
var OHW_BLUE_DARK = `color-mix(in srgb, var(--ohw-primary, ${PRIMARY5}) 60%, #000000)`;
|
|
19977
20184
|
function findVideoBlockElement(sectionId, path) {
|
|
19978
20185
|
const sectionEl = findByInstanceId(sectionId);
|
|
19979
20186
|
if (!sectionEl) return null;
|
|
@@ -20033,12 +20240,12 @@ function requestValidateTree3(postToParent2, tree) {
|
|
|
20033
20240
|
postToParent2({ type: "ow:ai-validate-tree-request", id, tree });
|
|
20034
20241
|
});
|
|
20035
20242
|
}
|
|
20036
|
-
function
|
|
20243
|
+
function Pill({
|
|
20037
20244
|
label,
|
|
20038
20245
|
onClick,
|
|
20039
20246
|
disabled
|
|
20040
20247
|
}) {
|
|
20041
|
-
return /* @__PURE__ */
|
|
20248
|
+
return /* @__PURE__ */ jsx23(
|
|
20042
20249
|
"button",
|
|
20043
20250
|
{
|
|
20044
20251
|
type: "button",
|
|
@@ -20054,7 +20261,7 @@ function Pill2({
|
|
|
20054
20261
|
border: "none",
|
|
20055
20262
|
cursor: disabled ? "default" : "pointer",
|
|
20056
20263
|
background: "#ffffff",
|
|
20057
|
-
color:
|
|
20264
|
+
color: OHW_BLUE_DARK,
|
|
20058
20265
|
opacity: disabled ? 0.4 : 1,
|
|
20059
20266
|
fontSize: 12,
|
|
20060
20267
|
lineHeight: "16px",
|
|
@@ -20076,7 +20283,7 @@ function VideoUrlInput({ value, onCommit }) {
|
|
|
20076
20283
|
setDraft(value ? watchUrl(value) : "");
|
|
20077
20284
|
setInvalid(false);
|
|
20078
20285
|
}, [value]);
|
|
20079
|
-
const
|
|
20286
|
+
const commit2 = () => {
|
|
20080
20287
|
const next = draft.trim();
|
|
20081
20288
|
if (!next) {
|
|
20082
20289
|
setInvalid(false);
|
|
@@ -20097,8 +20304,8 @@ function VideoUrlInput({ value, onCommit }) {
|
|
|
20097
20304
|
onCommit(id);
|
|
20098
20305
|
}
|
|
20099
20306
|
};
|
|
20100
|
-
return /* @__PURE__ */
|
|
20101
|
-
/* @__PURE__ */
|
|
20307
|
+
return /* @__PURE__ */ jsxs14("div", { style: { display: "flex", flexDirection: "column", gap: 4, width: "100%", maxWidth: 280 }, children: [
|
|
20308
|
+
/* @__PURE__ */ jsxs14(
|
|
20102
20309
|
"div",
|
|
20103
20310
|
{
|
|
20104
20311
|
style: {
|
|
@@ -20114,12 +20321,12 @@ function VideoUrlInput({ value, onCommit }) {
|
|
|
20114
20321
|
boxShadow: invalid ? "inset 0 0 0 1.5px #EF4444" : "none"
|
|
20115
20322
|
},
|
|
20116
20323
|
children: [
|
|
20117
|
-
/* @__PURE__ */
|
|
20324
|
+
/* @__PURE__ */ jsx23(
|
|
20118
20325
|
"span",
|
|
20119
20326
|
{
|
|
20120
20327
|
style: {
|
|
20121
20328
|
flex: "0 0 auto",
|
|
20122
|
-
color:
|
|
20329
|
+
color: OHW_BLUE_DARK,
|
|
20123
20330
|
fontSize: 10,
|
|
20124
20331
|
lineHeight: "16px",
|
|
20125
20332
|
fontWeight: 700,
|
|
@@ -20129,14 +20336,14 @@ function VideoUrlInput({ value, onCommit }) {
|
|
|
20129
20336
|
children: "Video"
|
|
20130
20337
|
}
|
|
20131
20338
|
),
|
|
20132
|
-
/* @__PURE__ */
|
|
20339
|
+
/* @__PURE__ */ jsx23(
|
|
20133
20340
|
"input",
|
|
20134
20341
|
{
|
|
20135
20342
|
type: "text",
|
|
20136
20343
|
inputMode: "url",
|
|
20137
20344
|
value: draft,
|
|
20138
20345
|
onChange: (e) => handleChange(e.target.value),
|
|
20139
|
-
onBlur:
|
|
20346
|
+
onBlur: commit2,
|
|
20140
20347
|
onKeyDown: (e) => {
|
|
20141
20348
|
if (e.key === "Enter") e.currentTarget.blur();
|
|
20142
20349
|
if (e.key === "Escape") {
|
|
@@ -20166,7 +20373,7 @@ function VideoUrlInput({ value, onCommit }) {
|
|
|
20166
20373
|
]
|
|
20167
20374
|
}
|
|
20168
20375
|
),
|
|
20169
|
-
invalid && /* @__PURE__ */
|
|
20376
|
+
invalid && /* @__PURE__ */ jsx23("div", { style: { color: "#FCA5A5", fontSize: 11, textAlign: "center" }, children: "That doesn't look like a YouTube link \u2014 try pasting the video URL again." })
|
|
20170
20377
|
] });
|
|
20171
20378
|
}
|
|
20172
20379
|
function VideoToolbar({
|
|
@@ -20176,7 +20383,7 @@ function VideoToolbar({
|
|
|
20176
20383
|
onSetVideoId,
|
|
20177
20384
|
onRemove
|
|
20178
20385
|
}) {
|
|
20179
|
-
return /* @__PURE__ */
|
|
20386
|
+
return /* @__PURE__ */ jsxs14(
|
|
20180
20387
|
"div",
|
|
20181
20388
|
{
|
|
20182
20389
|
"data-ohw-bridge": "",
|
|
@@ -20188,7 +20395,7 @@ function VideoToolbar({
|
|
|
20188
20395
|
gap: 6,
|
|
20189
20396
|
alignItems: "center",
|
|
20190
20397
|
width: 280,
|
|
20191
|
-
background:
|
|
20398
|
+
background: OHW_BLUE,
|
|
20192
20399
|
padding: 8,
|
|
20193
20400
|
borderRadius: 12,
|
|
20194
20401
|
boxShadow: "0 8px 24px rgba(0,0,0,0.25)",
|
|
@@ -20196,9 +20403,9 @@ function VideoToolbar({
|
|
|
20196
20403
|
opacity: pending ? 0.6 : 1
|
|
20197
20404
|
},
|
|
20198
20405
|
children: [
|
|
20199
|
-
/* @__PURE__ */
|
|
20200
|
-
/* @__PURE__ */
|
|
20201
|
-
error && /* @__PURE__ */
|
|
20406
|
+
/* @__PURE__ */ jsx23(VideoUrlInput, { value: videoId, onCommit: onSetVideoId }),
|
|
20407
|
+
/* @__PURE__ */ jsx23(Pill, { label: "Remove video", onClick: onRemove, disabled: !videoId }),
|
|
20408
|
+
error && /* @__PURE__ */ jsx23("div", { style: { color: "#FCA5A5", fontSize: 11, maxWidth: 220, textAlign: "center" }, children: error })
|
|
20202
20409
|
]
|
|
20203
20410
|
}
|
|
20204
20411
|
);
|
|
@@ -20318,8 +20525,8 @@ function AiVideoOverlay({
|
|
|
20318
20525
|
const activeBlockRect = useLiveBlockRect(active);
|
|
20319
20526
|
const TOOLBAR_APPROX_H = 90;
|
|
20320
20527
|
const toolbarState = activeBlockRect && activeBlockRect.top < TOOLBAR_APPROX_H ? "active-bottom" : "active-top";
|
|
20321
|
-
return /* @__PURE__ */
|
|
20322
|
-
hoverHandleRect && hover && /* @__PURE__ */
|
|
20528
|
+
return /* @__PURE__ */ jsxs14(Fragment9, { children: [
|
|
20529
|
+
hoverHandleRect && hover && /* @__PURE__ */ jsx23(
|
|
20323
20530
|
"button",
|
|
20324
20531
|
{
|
|
20325
20532
|
type: "button",
|
|
@@ -20347,15 +20554,15 @@ function AiVideoOverlay({
|
|
|
20347
20554
|
fontSize: 14,
|
|
20348
20555
|
fontWeight: 700
|
|
20349
20556
|
},
|
|
20350
|
-
children: /* @__PURE__ */
|
|
20557
|
+
children: /* @__PURE__ */ jsx23(Star3, { size: 14, style: { pointerEvents: "none" } })
|
|
20351
20558
|
}
|
|
20352
20559
|
),
|
|
20353
|
-
activeBlockRect && active && activeEntry && /* @__PURE__ */
|
|
20560
|
+
activeBlockRect && active && activeEntry && /* @__PURE__ */ jsx23(
|
|
20354
20561
|
ItemInteractionLayer,
|
|
20355
20562
|
{
|
|
20356
20563
|
rect: activeBlockRect,
|
|
20357
20564
|
state: toolbarState,
|
|
20358
|
-
toolbar: /* @__PURE__ */
|
|
20565
|
+
toolbar: /* @__PURE__ */ jsx23(
|
|
20359
20566
|
VideoToolbar,
|
|
20360
20567
|
{
|
|
20361
20568
|
videoId: videoIdAt(activeEntry.tree, active.path),
|
|
@@ -20430,10 +20637,10 @@ function setCarouselAutoplay(tree, on) {
|
|
|
20430
20637
|
}
|
|
20431
20638
|
|
|
20432
20639
|
// src/ui/ai-section/AiFadeCarouselOverlay.tsx
|
|
20433
|
-
import { Fragment as Fragment10, jsx as
|
|
20640
|
+
import { Fragment as Fragment10, jsx as jsx24, jsxs as jsxs15 } from "react/jsx-runtime";
|
|
20434
20641
|
var PRIMARY6 = "#0885FE";
|
|
20435
|
-
var
|
|
20436
|
-
var
|
|
20642
|
+
var OHW_BLUE2 = `var(--ohw-primary, ${PRIMARY6})`;
|
|
20643
|
+
var OHW_BLUE_DARK2 = `color-mix(in srgb, var(--ohw-primary, ${PRIMARY6}) 60%, #000000)`;
|
|
20437
20644
|
function findCarouselItemElement(sectionId, index) {
|
|
20438
20645
|
const sectionEl = findByInstanceId(sectionId);
|
|
20439
20646
|
if (!sectionEl) return null;
|
|
@@ -20512,8 +20719,8 @@ function requestAssetPick2(postToParent2) {
|
|
|
20512
20719
|
postToParent2({ type: "ow:asset-pick", id });
|
|
20513
20720
|
});
|
|
20514
20721
|
}
|
|
20515
|
-
function
|
|
20516
|
-
return /* @__PURE__ */
|
|
20722
|
+
function Pill2({ label, onClick, disabled }) {
|
|
20723
|
+
return /* @__PURE__ */ jsx24(
|
|
20517
20724
|
"button",
|
|
20518
20725
|
{
|
|
20519
20726
|
type: "button",
|
|
@@ -20529,7 +20736,7 @@ function Pill3({ label, onClick, disabled }) {
|
|
|
20529
20736
|
border: "none",
|
|
20530
20737
|
cursor: disabled ? "default" : "pointer",
|
|
20531
20738
|
background: "#ffffff",
|
|
20532
|
-
color:
|
|
20739
|
+
color: OHW_BLUE_DARK2,
|
|
20533
20740
|
opacity: disabled ? 0.4 : 1,
|
|
20534
20741
|
fontSize: 12,
|
|
20535
20742
|
lineHeight: "16px",
|
|
@@ -20547,7 +20754,7 @@ function TogglePill({
|
|
|
20547
20754
|
onToggle,
|
|
20548
20755
|
disabled
|
|
20549
20756
|
}) {
|
|
20550
|
-
return /* @__PURE__ */
|
|
20757
|
+
return /* @__PURE__ */ jsxs15(
|
|
20551
20758
|
"button",
|
|
20552
20759
|
{
|
|
20553
20760
|
type: "button",
|
|
@@ -20566,7 +20773,7 @@ function TogglePill({
|
|
|
20566
20773
|
border: "none",
|
|
20567
20774
|
cursor: disabled ? "default" : "pointer",
|
|
20568
20775
|
background: "#ffffff",
|
|
20569
|
-
color:
|
|
20776
|
+
color: OHW_BLUE_DARK2,
|
|
20570
20777
|
opacity: disabled ? 0.4 : 1,
|
|
20571
20778
|
fontSize: 12,
|
|
20572
20779
|
lineHeight: "16px",
|
|
@@ -20576,7 +20783,7 @@ function TogglePill({
|
|
|
20576
20783
|
},
|
|
20577
20784
|
children: [
|
|
20578
20785
|
label,
|
|
20579
|
-
/* @__PURE__ */
|
|
20786
|
+
/* @__PURE__ */ jsx24(
|
|
20580
20787
|
"span",
|
|
20581
20788
|
{
|
|
20582
20789
|
"aria-hidden": true,
|
|
@@ -20589,10 +20796,10 @@ function TogglePill({
|
|
|
20589
20796
|
// Off is a grey track, not a washed-out blue: the pill's own white background already
|
|
20590
20797
|
// carries the brand colour in the text, and a pale blue track next to it read as
|
|
20591
20798
|
// "disabled control" rather than "switch that is off".
|
|
20592
|
-
background: on ?
|
|
20799
|
+
background: on ? OHW_BLUE_DARK2 : "#CBD5E1",
|
|
20593
20800
|
transition: "background 120ms ease"
|
|
20594
20801
|
},
|
|
20595
|
-
children: /* @__PURE__ */
|
|
20802
|
+
children: /* @__PURE__ */ jsx24(
|
|
20596
20803
|
"span",
|
|
20597
20804
|
{
|
|
20598
20805
|
style: {
|
|
@@ -20621,7 +20828,7 @@ function CarouselSlideToolbar({
|
|
|
20621
20828
|
onChangeImage,
|
|
20622
20829
|
onToggleAutoplay
|
|
20623
20830
|
}) {
|
|
20624
|
-
return /* @__PURE__ */
|
|
20831
|
+
return /* @__PURE__ */ jsxs15(
|
|
20625
20832
|
"div",
|
|
20626
20833
|
{
|
|
20627
20834
|
"data-ohw-bridge": "",
|
|
@@ -20632,7 +20839,7 @@ function CarouselSlideToolbar({
|
|
|
20632
20839
|
flexDirection: "column",
|
|
20633
20840
|
gap: 6,
|
|
20634
20841
|
alignItems: "center",
|
|
20635
|
-
background:
|
|
20842
|
+
background: OHW_BLUE2,
|
|
20636
20843
|
padding: 8,
|
|
20637
20844
|
borderRadius: 12,
|
|
20638
20845
|
boxShadow: "0 8px 24px rgba(0,0,0,0.25)",
|
|
@@ -20644,11 +20851,11 @@ function CarouselSlideToolbar({
|
|
|
20644
20851
|
pointerEvents: pending ? "none" : "auto"
|
|
20645
20852
|
},
|
|
20646
20853
|
children: [
|
|
20647
|
-
/* @__PURE__ */
|
|
20648
|
-
/* @__PURE__ */
|
|
20649
|
-
/* @__PURE__ */
|
|
20854
|
+
/* @__PURE__ */ jsxs15("div", { style: { display: "flex", gap: 6, alignItems: "center" }, children: [
|
|
20855
|
+
/* @__PURE__ */ jsx24(Pill2, { label: "Change Image", onClick: onChangeImage }),
|
|
20856
|
+
/* @__PURE__ */ jsx24(TogglePill, { label: "Autoplay", on: autoplay, onToggle: onToggleAutoplay })
|
|
20650
20857
|
] }),
|
|
20651
|
-
error && /* @__PURE__ */
|
|
20858
|
+
error && /* @__PURE__ */ jsx24("div", { style: { color: "#FCA5A5", fontSize: 11, maxWidth: 220, textAlign: "center" }, children: error })
|
|
20652
20859
|
]
|
|
20653
20860
|
}
|
|
20654
20861
|
);
|
|
@@ -20788,8 +20995,8 @@ function AiFadeCarouselOverlay({
|
|
|
20788
20995
|
const activeItemRect = useLiveItemRect2(active);
|
|
20789
20996
|
const TOOLBAR_APPROX_H = 90;
|
|
20790
20997
|
const toolbarState = activeItemRect && activeItemRect.top < TOOLBAR_APPROX_H ? "active-bottom" : "active-top";
|
|
20791
|
-
return /* @__PURE__ */
|
|
20792
|
-
hoverHandleRect && hover && /* @__PURE__ */
|
|
20998
|
+
return /* @__PURE__ */ jsxs15(Fragment10, { children: [
|
|
20999
|
+
hoverHandleRect && hover && /* @__PURE__ */ jsx24(
|
|
20793
21000
|
"button",
|
|
20794
21001
|
{
|
|
20795
21002
|
type: "button",
|
|
@@ -20818,10 +21025,10 @@ function AiFadeCarouselOverlay({
|
|
|
20818
21025
|
fontSize: 14,
|
|
20819
21026
|
fontWeight: 700
|
|
20820
21027
|
},
|
|
20821
|
-
children: /* @__PURE__ */
|
|
21028
|
+
children: /* @__PURE__ */ jsx24(Star4, { size: 14, style: { pointerEvents: "none" } })
|
|
20822
21029
|
}
|
|
20823
21030
|
),
|
|
20824
|
-
swapping && /* @__PURE__ */
|
|
21031
|
+
swapping && /* @__PURE__ */ jsx24(
|
|
20825
21032
|
"div",
|
|
20826
21033
|
{
|
|
20827
21034
|
ref: skeletonRef,
|
|
@@ -20839,15 +21046,15 @@ function AiFadeCarouselOverlay({
|
|
|
20839
21046
|
zIndex: 2147483646,
|
|
20840
21047
|
pointerEvents: "none"
|
|
20841
21048
|
},
|
|
20842
|
-
children: /* @__PURE__ */
|
|
21049
|
+
children: /* @__PURE__ */ jsx24("style", { children: MEDIA_SKELETON_CSS })
|
|
20843
21050
|
}
|
|
20844
21051
|
),
|
|
20845
|
-
activeItemRect && active && activeEntry && /* @__PURE__ */
|
|
21052
|
+
activeItemRect && active && activeEntry && /* @__PURE__ */ jsx24(
|
|
20846
21053
|
ItemInteractionLayer,
|
|
20847
21054
|
{
|
|
20848
21055
|
rect: activeItemRect,
|
|
20849
21056
|
state: toolbarState,
|
|
20850
|
-
toolbar: /* @__PURE__ */
|
|
21057
|
+
toolbar: /* @__PURE__ */ jsx24(
|
|
20851
21058
|
CarouselSlideToolbar,
|
|
20852
21059
|
{
|
|
20853
21060
|
pending,
|
|
@@ -21065,118 +21272,11 @@ function scrollToHashSectionWhenReady(behavior = "smooth") {
|
|
|
21065
21272
|
// src/ui/link-modal/LinkPopover.tsx
|
|
21066
21273
|
import { useEffect as useEffect13 } from "react";
|
|
21067
21274
|
|
|
21068
|
-
// src/ui/dialog.tsx
|
|
21069
|
-
import * as React9 from "react";
|
|
21070
|
-
import { Dialog as DialogPrimitive } from "radix-ui";
|
|
21071
|
-
import { X as X2 } from "lucide-react";
|
|
21072
|
-
import { jsx as jsx24, jsxs as jsxs15 } from "react/jsx-runtime";
|
|
21073
|
-
function Dialog2({
|
|
21074
|
-
...props
|
|
21075
|
-
}) {
|
|
21076
|
-
return /* @__PURE__ */ jsx24(DialogPrimitive.Root, { "data-slot": "dialog", ...props });
|
|
21077
|
-
}
|
|
21078
|
-
function DialogPortal({
|
|
21079
|
-
...props
|
|
21080
|
-
}) {
|
|
21081
|
-
return /* @__PURE__ */ jsx24(DialogPrimitive.Portal, { ...props });
|
|
21082
|
-
}
|
|
21083
|
-
function DialogOverlay({
|
|
21084
|
-
className,
|
|
21085
|
-
...props
|
|
21086
|
-
}) {
|
|
21087
|
-
return /* @__PURE__ */ jsx24(
|
|
21088
|
-
DialogPrimitive.Overlay,
|
|
21089
|
-
{
|
|
21090
|
-
"data-slot": "dialog-overlay",
|
|
21091
|
-
"data-ohw-link-modal-root": "",
|
|
21092
|
-
className: cn("fixed inset-0 z-[2147483646] bg-black/50", className),
|
|
21093
|
-
...props
|
|
21094
|
-
}
|
|
21095
|
-
);
|
|
21096
|
-
}
|
|
21097
|
-
var DialogContent = React9.forwardRef(
|
|
21098
|
-
({ className, children, showCloseButton = true, container, ...props }, ref) => {
|
|
21099
|
-
const positionMode = container ? "absolute" : "fixed";
|
|
21100
|
-
return /* @__PURE__ */ jsxs15(DialogPortal, { container: container ?? void 0, children: [
|
|
21101
|
-
/* @__PURE__ */ jsx24(DialogOverlay, { className: cn(positionMode, "inset-0") }),
|
|
21102
|
-
/* @__PURE__ */ jsxs15(
|
|
21103
|
-
DialogPrimitive.Content,
|
|
21104
|
-
{
|
|
21105
|
-
ref,
|
|
21106
|
-
"data-slot": "dialog-content",
|
|
21107
|
-
className: cn(
|
|
21108
|
-
positionMode,
|
|
21109
|
-
"left-1/2 top-1/2 z-[2147483647] flex w-full max-w-[448px] -translate-x-1/2 -translate-y-1/2 flex-col overflow-visible",
|
|
21110
|
-
"rounded-xl border border-border bg-background font-sans shadow-lg outline-none",
|
|
21111
|
-
container ? "max-h-[calc(100%-32px)]" : "max-h-[calc(100vh-32px)]",
|
|
21112
|
-
className
|
|
21113
|
-
),
|
|
21114
|
-
onMouseDown: (e) => e.stopPropagation(),
|
|
21115
|
-
...props,
|
|
21116
|
-
children: [
|
|
21117
|
-
children,
|
|
21118
|
-
showCloseButton ? /* @__PURE__ */ jsx24(
|
|
21119
|
-
DialogPrimitive.Close,
|
|
21120
|
-
{
|
|
21121
|
-
type: "button",
|
|
21122
|
-
className: "absolute right-[9px] top-[9px] rounded-sm p-1.5 text-foreground hover:bg-muted/50",
|
|
21123
|
-
"aria-label": "Close",
|
|
21124
|
-
children: /* @__PURE__ */ jsx24(X2, { size: 16, "aria-hidden": true })
|
|
21125
|
-
}
|
|
21126
|
-
) : null
|
|
21127
|
-
]
|
|
21128
|
-
}
|
|
21129
|
-
)
|
|
21130
|
-
] });
|
|
21131
|
-
}
|
|
21132
|
-
);
|
|
21133
|
-
DialogContent.displayName = DialogPrimitive.Content.displayName;
|
|
21134
|
-
function DialogHeader({
|
|
21135
|
-
className,
|
|
21136
|
-
...props
|
|
21137
|
-
}) {
|
|
21138
|
-
return /* @__PURE__ */ jsx24("div", { className: cn("flex flex-col gap-1.5", className), ...props });
|
|
21139
|
-
}
|
|
21140
|
-
function DialogFooter({
|
|
21141
|
-
className,
|
|
21142
|
-
...props
|
|
21143
|
-
}) {
|
|
21144
|
-
return /* @__PURE__ */ jsx24(
|
|
21145
|
-
"div",
|
|
21146
|
-
{
|
|
21147
|
-
className: cn("flex items-center justify-end gap-2", className),
|
|
21148
|
-
...props
|
|
21149
|
-
}
|
|
21150
|
-
);
|
|
21151
|
-
}
|
|
21152
|
-
var DialogTitle = React9.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx24(
|
|
21153
|
-
DialogPrimitive.Title,
|
|
21154
|
-
{
|
|
21155
|
-
ref,
|
|
21156
|
-
className: cn(
|
|
21157
|
-
"text-lg font-semibold leading-none tracking-tight text-card-foreground",
|
|
21158
|
-
className
|
|
21159
|
-
),
|
|
21160
|
-
...props
|
|
21161
|
-
}
|
|
21162
|
-
));
|
|
21163
|
-
DialogTitle.displayName = DialogPrimitive.Title.displayName;
|
|
21164
|
-
var DialogDescription = React9.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx24(
|
|
21165
|
-
DialogPrimitive.Description,
|
|
21166
|
-
{
|
|
21167
|
-
ref,
|
|
21168
|
-
className: cn("text-sm text-muted-foreground", className),
|
|
21169
|
-
...props
|
|
21170
|
-
}
|
|
21171
|
-
));
|
|
21172
|
-
DialogDescription.displayName = DialogPrimitive.Description.displayName;
|
|
21173
|
-
var DialogClose = DialogPrimitive.Close;
|
|
21174
|
-
|
|
21175
21275
|
// src/ui/link-modal/LinkEditorPanel.tsx
|
|
21176
21276
|
import { Info, X as X4 } from "lucide-react";
|
|
21177
21277
|
|
|
21178
21278
|
// src/ui/link-modal/DestinationBreadcrumb.tsx
|
|
21179
|
-
import { ArrowRight as
|
|
21279
|
+
import { ArrowRight as ArrowRight3, File, GalleryVertical } from "lucide-react";
|
|
21180
21280
|
import { jsx as jsx25, jsxs as jsxs16 } from "react/jsx-runtime";
|
|
21181
21281
|
function DestinationBreadcrumb({
|
|
21182
21282
|
pageTitle,
|
|
@@ -21190,7 +21290,7 @@ function DestinationBreadcrumb({
|
|
|
21190
21290
|
/* @__PURE__ */ jsx25("span", { className: "text-sm font-medium leading-none text-foreground!", children: pageTitle })
|
|
21191
21291
|
] }),
|
|
21192
21292
|
/* @__PURE__ */ jsx25(
|
|
21193
|
-
|
|
21293
|
+
ArrowRight3,
|
|
21194
21294
|
{
|
|
21195
21295
|
size: 16,
|
|
21196
21296
|
className: "shrink-0 text-muted-foreground",
|
|
@@ -21302,7 +21402,7 @@ function Label({ className, ...props }) {
|
|
|
21302
21402
|
}
|
|
21303
21403
|
|
|
21304
21404
|
// src/ui/link-modal/UrlOrPageInput.tsx
|
|
21305
|
-
import { ChevronDown as
|
|
21405
|
+
import { ChevronDown as ChevronDown5, File as File2, X as X3 } from "lucide-react";
|
|
21306
21406
|
import { jsx as jsx29, jsxs as jsxs18 } from "react/jsx-runtime";
|
|
21307
21407
|
function FieldChevron({
|
|
21308
21408
|
onClick
|
|
@@ -21315,7 +21415,7 @@ function FieldChevron({
|
|
|
21315
21415
|
onClick,
|
|
21316
21416
|
"aria-label": "Open page list",
|
|
21317
21417
|
tabIndex: -1,
|
|
21318
|
-
children: /* @__PURE__ */ jsx29(
|
|
21418
|
+
children: /* @__PURE__ */ jsx29(ChevronDown5, { size: 16 })
|
|
21319
21419
|
}
|
|
21320
21420
|
);
|
|
21321
21421
|
}
|
|
@@ -21545,7 +21645,7 @@ function LinkEditorPanel({ state, onClose }) {
|
|
|
21545
21645
|
// src/ui/link-modal/SectionPickerOverlay.tsx
|
|
21546
21646
|
import { useCallback as useCallback7, useEffect as useEffect11, useMemo as useMemo2, useRef as useRef10, useState as useState13 } from "react";
|
|
21547
21647
|
import { createPortal as createPortal2 } from "react-dom";
|
|
21548
|
-
import { ArrowLeft as
|
|
21648
|
+
import { ArrowLeft as ArrowLeft3, Check as Check4 } from "lucide-react";
|
|
21549
21649
|
import { usePathname, useRouter as useRouter2 } from "next/navigation";
|
|
21550
21650
|
|
|
21551
21651
|
// src/lib/parent-scroll.ts
|
|
@@ -21822,7 +21922,7 @@ function SectionPickerOverlay({
|
|
|
21822
21922
|
className: "h-8 min-w-0 gap-1 border-border bg-background px-2 py-1.5 shadow-sm hover:bg-muted cursor-pointer",
|
|
21823
21923
|
onClick: onBack,
|
|
21824
21924
|
children: [
|
|
21825
|
-
/* @__PURE__ */ jsx31(
|
|
21925
|
+
/* @__PURE__ */ jsx31(ArrowLeft3, { className: "size-4 shrink-0", "aria-hidden": true }),
|
|
21826
21926
|
"Back"
|
|
21827
21927
|
]
|
|
21828
21928
|
}
|
|
@@ -21891,7 +21991,7 @@ function SectionPickerOverlay({
|
|
|
21891
21991
|
className: "absolute right-3 top-3 flex size-8 items-center justify-center rounded-full text-white",
|
|
21892
21992
|
style: { backgroundColor: "var(--ohw-primary, #0885fe)" },
|
|
21893
21993
|
"aria-hidden": true,
|
|
21894
|
-
children: /* @__PURE__ */ jsx31(
|
|
21994
|
+
children: /* @__PURE__ */ jsx31(Check4, { className: "size-5" })
|
|
21895
21995
|
}
|
|
21896
21996
|
) : null
|
|
21897
21997
|
]
|
|
@@ -22275,6 +22375,7 @@ function shouldUseDevFixtures() {
|
|
|
22275
22375
|
function getLogoElement(el) {
|
|
22276
22376
|
const marked = el.closest('[data-ohw-role="logo"], [data-ohw-logo]');
|
|
22277
22377
|
if (marked) return marked;
|
|
22378
|
+
if (el.closest('[data-ohw-editable="icon"]')) return null;
|
|
22278
22379
|
const root = el.closest("nav, [data-ohw-nav-root], footer");
|
|
22279
22380
|
if (!root) return null;
|
|
22280
22381
|
const anchor = el.closest("a");
|
|
@@ -22344,7 +22445,7 @@ function addFooterColumnWithPersist({
|
|
|
22344
22445
|
import {
|
|
22345
22446
|
useCallback as useCallback9,
|
|
22346
22447
|
useEffect as useEffect14,
|
|
22347
|
-
useLayoutEffect as
|
|
22448
|
+
useLayoutEffect as useLayoutEffect6,
|
|
22348
22449
|
useRef as useRef11,
|
|
22349
22450
|
useState as useState15
|
|
22350
22451
|
} from "react";
|
|
@@ -22441,7 +22542,7 @@ function FloatingPanel({
|
|
|
22441
22542
|
return () => window.removeEventListener("message", onParentScroll);
|
|
22442
22543
|
}, [open]);
|
|
22443
22544
|
const positionRef = useRef11(position);
|
|
22444
|
-
|
|
22545
|
+
useLayoutEffect6(() => {
|
|
22445
22546
|
if (!open) {
|
|
22446
22547
|
positionRef.current = position;
|
|
22447
22548
|
return;
|
|
@@ -22451,7 +22552,7 @@ function FloatingPanel({
|
|
|
22451
22552
|
}
|
|
22452
22553
|
positionRef.current = position;
|
|
22453
22554
|
}, [open, position, liveScroll, parentScroll]);
|
|
22454
|
-
|
|
22555
|
+
useLayoutEffect6(() => {
|
|
22455
22556
|
if (!open || !panelRef.current) return;
|
|
22456
22557
|
const el = panelRef.current;
|
|
22457
22558
|
const header = el.querySelector("[data-ohw-floating-panel-header]");
|
|
@@ -22660,7 +22761,7 @@ function SocialsDisplayPanel({ display, onChange, className }) {
|
|
|
22660
22761
|
}
|
|
22661
22762
|
|
|
22662
22763
|
// src/ui/button-style-panel.tsx
|
|
22663
|
-
import { Check as
|
|
22764
|
+
import { Check as Check5 } from "lucide-react";
|
|
22664
22765
|
import { jsx as jsx35, jsxs as jsxs24 } from "react/jsx-runtime";
|
|
22665
22766
|
var SIZE_LABEL = { s: "S", m: "M", l: "L" };
|
|
22666
22767
|
function ButtonStylePanel({
|
|
@@ -22731,7 +22832,7 @@ function ButtonStylePanel({
|
|
|
22731
22832
|
{
|
|
22732
22833
|
className: "absolute right-0.5 top-0.5 flex size-5 items-center justify-center rounded-full bg-primary text-primary-foreground",
|
|
22733
22834
|
"aria-hidden": true,
|
|
22734
|
-
children: /* @__PURE__ */ jsx35(
|
|
22835
|
+
children: /* @__PURE__ */ jsx35(Check5, { className: "size-3", strokeWidth: 3 })
|
|
22735
22836
|
}
|
|
22736
22837
|
) : null
|
|
22737
22838
|
]
|
|
@@ -23756,7 +23857,7 @@ function useSectionDrag({
|
|
|
23756
23857
|
}
|
|
23757
23858
|
|
|
23758
23859
|
// src/ui/footer-container-chrome.tsx
|
|
23759
|
-
import { Plus as
|
|
23860
|
+
import { Plus as Plus4 } from "lucide-react";
|
|
23760
23861
|
import { jsx as jsx36, jsxs as jsxs25 } from "react/jsx-runtime";
|
|
23761
23862
|
function FooterContainerChrome({
|
|
23762
23863
|
rect,
|
|
@@ -23797,7 +23898,7 @@ function FooterContainerChrome({
|
|
|
23797
23898
|
if (addDisabled) return;
|
|
23798
23899
|
onAdd();
|
|
23799
23900
|
},
|
|
23800
|
-
children: /* @__PURE__ */ jsx36(
|
|
23901
|
+
children: /* @__PURE__ */ jsx36(Plus4, { className: "size-4 shrink-0 text-foreground", "aria-hidden": true })
|
|
23801
23902
|
}
|
|
23802
23903
|
) }),
|
|
23803
23904
|
/* @__PURE__ */ jsx36(TooltipContent, { side: "bottom", sideOffset: 9, children: addDisabled ? "Maximum columns reached" : "Add item" })
|
|
@@ -23975,8 +24076,104 @@ function deleteSelectedNavFooterItem(deps) {
|
|
|
23975
24076
|
return false;
|
|
23976
24077
|
}
|
|
23977
24078
|
|
|
24079
|
+
// src/lib/nav-page-sync.ts
|
|
24080
|
+
function labelKeyFor(hrefKey) {
|
|
24081
|
+
return hrefKey.replace(/-href$/, "-label");
|
|
24082
|
+
}
|
|
24083
|
+
function isPageLinkKey(key) {
|
|
24084
|
+
return isNavbarHrefKey(key) || isFooterHrefKey(key);
|
|
24085
|
+
}
|
|
24086
|
+
function currentHref(key, anchor, content) {
|
|
24087
|
+
const stored = content[key];
|
|
24088
|
+
if (typeof stored === "string" && stored.length > 0) return stored;
|
|
24089
|
+
return anchor.getAttribute("href") ?? "";
|
|
24090
|
+
}
|
|
24091
|
+
function normalizePath2(value) {
|
|
24092
|
+
if (value.length > 1 && value.endsWith("/")) return value.slice(0, -1);
|
|
24093
|
+
return value;
|
|
24094
|
+
}
|
|
24095
|
+
function pointsAt(href, path) {
|
|
24096
|
+
const normalized = normalizePath2(href);
|
|
24097
|
+
const target = normalizePath2(path);
|
|
24098
|
+
if (normalized === target) return true;
|
|
24099
|
+
return (normalized.startsWith(`${target}#`) || normalized.startsWith(`${target}?`)) && target !== "/";
|
|
24100
|
+
}
|
|
24101
|
+
function retargetHref(href, oldPath, newPath) {
|
|
24102
|
+
const normalized = normalizePath2(href);
|
|
24103
|
+
const target = normalizePath2(oldPath);
|
|
24104
|
+
if (normalized === target) return newPath;
|
|
24105
|
+
return `${newPath}${normalized.slice(target.length)}`;
|
|
24106
|
+
}
|
|
24107
|
+
function setLabelText(key, text) {
|
|
24108
|
+
document.querySelectorAll(`[data-ohw-key="${CSS.escape(key)}"]`).forEach((el) => {
|
|
24109
|
+
el.textContent = text;
|
|
24110
|
+
});
|
|
24111
|
+
}
|
|
24112
|
+
function commit(delta, deps) {
|
|
24113
|
+
if (Object.keys(delta).length === 0) return;
|
|
24114
|
+
deps.setEditContent({ ...deps.getEditContent(), ...delta });
|
|
24115
|
+
deps.postToParent({
|
|
24116
|
+
type: "ow:change",
|
|
24117
|
+
nodes: Object.entries(delta).map(([key, text]) => ({ key, text }))
|
|
24118
|
+
});
|
|
24119
|
+
}
|
|
24120
|
+
function navLinksTo(path, content) {
|
|
24121
|
+
return Array.from(document.querySelectorAll("[data-ohw-href-key]")).filter((anchor) => {
|
|
24122
|
+
const key = anchor.getAttribute("data-ohw-href-key");
|
|
24123
|
+
return isNavbarHrefKey(key) && pointsAt(currentHref(key, anchor, content), path);
|
|
24124
|
+
}).map((anchor) => anchor.getAttribute("data-ohw-href-key"));
|
|
24125
|
+
}
|
|
24126
|
+
function addNavLinkForPage(page, deps) {
|
|
24127
|
+
const content = deps.getEditContent();
|
|
24128
|
+
if (navLinksTo(page.path, content).length > 0) return false;
|
|
24129
|
+
const roots = listNavbarRootItems();
|
|
24130
|
+
const afterAnchor = roots[roots.length - 1] ?? null;
|
|
24131
|
+
let inserted;
|
|
24132
|
+
try {
|
|
24133
|
+
inserted = insertNavbarItem(page.path, page.title, afterAnchor);
|
|
24134
|
+
} catch {
|
|
24135
|
+
return false;
|
|
24136
|
+
}
|
|
24137
|
+
const { hrefKey, labelKey, index } = inserted;
|
|
24138
|
+
deps.applyLinkByKey(hrefKey, page.path);
|
|
24139
|
+
setLabelText(labelKey, page.title);
|
|
24140
|
+
commit(
|
|
24141
|
+
{
|
|
24142
|
+
[hrefKey]: page.path,
|
|
24143
|
+
[labelKey]: page.title,
|
|
24144
|
+
[NAV_COUNT_KEY]: String(index + 1),
|
|
24145
|
+
[NAV_ORDER_KEY]: getNavbarOrderJson()
|
|
24146
|
+
},
|
|
24147
|
+
deps
|
|
24148
|
+
);
|
|
24149
|
+
return true;
|
|
24150
|
+
}
|
|
24151
|
+
function retargetPageLinks(change, deps) {
|
|
24152
|
+
const { oldPath, newPath, oldTitle, newTitle } = change;
|
|
24153
|
+
if (!oldPath || !newPath || normalizePath2(oldPath) === normalizePath2(newPath)) return 0;
|
|
24154
|
+
const content = deps.getEditContent();
|
|
24155
|
+
const delta = {};
|
|
24156
|
+
for (const anchor of Array.from(document.querySelectorAll("[data-ohw-href-key]"))) {
|
|
24157
|
+
const hrefKey = anchor.getAttribute("data-ohw-href-key");
|
|
24158
|
+
if (!isPageLinkKey(hrefKey)) continue;
|
|
24159
|
+
const href = currentHref(hrefKey, anchor, content);
|
|
24160
|
+
if (!pointsAt(href, oldPath)) continue;
|
|
24161
|
+
const nextHref = retargetHref(href, oldPath, newPath);
|
|
24162
|
+
deps.applyLinkByKey(hrefKey, nextHref);
|
|
24163
|
+
delta[hrefKey] = nextHref;
|
|
24164
|
+
if (!oldTitle || !newTitle) continue;
|
|
24165
|
+
const labelKey = labelKeyFor(hrefKey);
|
|
24166
|
+
const label = content[labelKey] ?? anchor.querySelector('[data-ohw-editable="text"]')?.textContent ?? "";
|
|
24167
|
+
if (label.trim() !== oldTitle) continue;
|
|
24168
|
+
setLabelText(labelKey, newTitle);
|
|
24169
|
+
delta[labelKey] = newTitle;
|
|
24170
|
+
}
|
|
24171
|
+
commit(delta, deps);
|
|
24172
|
+
return Object.keys(delta).filter((key) => key.endsWith("-href")).length;
|
|
24173
|
+
}
|
|
24174
|
+
|
|
23978
24175
|
// src/ui/navbar-container-chrome.tsx
|
|
23979
|
-
import { Plus as
|
|
24176
|
+
import { Plus as Plus5 } from "lucide-react";
|
|
23980
24177
|
import { jsx as jsx37 } from "react/jsx-runtime";
|
|
23981
24178
|
function NavbarContainerChrome({
|
|
23982
24179
|
rect,
|
|
@@ -24012,7 +24209,7 @@ function NavbarContainerChrome({
|
|
|
24012
24209
|
e.stopPropagation();
|
|
24013
24210
|
onAdd();
|
|
24014
24211
|
},
|
|
24015
|
-
children: /* @__PURE__ */ jsx37(
|
|
24212
|
+
children: /* @__PURE__ */ jsx37(Plus5, { className: "size-4 shrink-0 text-foreground", "aria-hidden": true })
|
|
24016
24213
|
}
|
|
24017
24214
|
)
|
|
24018
24215
|
}
|
|
@@ -24084,7 +24281,7 @@ function Badge({ className, variant, ...props }) {
|
|
|
24084
24281
|
}
|
|
24085
24282
|
|
|
24086
24283
|
// src/OhhwellsBridge.tsx
|
|
24087
|
-
import { Brush as Brush2, Link as Link2, Plus as
|
|
24284
|
+
import { Brush as Brush2, Link as Link2, Plus as Plus6, Settings } from "lucide-react";
|
|
24088
24285
|
import { Fragment as Fragment13, jsx as jsx40, jsxs as jsxs26 } from "react/jsx-runtime";
|
|
24089
24286
|
var PRIMARY7 = "#0885FE";
|
|
24090
24287
|
var IMAGE_FADE_MS = 300;
|
|
@@ -24862,7 +25059,7 @@ function getNavigationSelectionParent(el) {
|
|
|
24862
25059
|
if (!isFooterLinksContainer(el) && (el.hasAttribute("data-ohw-footer-col") || el.hasAttribute("data-ohw-footer-column") || isInferredFooterGroup2(el))) {
|
|
24863
25060
|
return resolveFooterLinksContainerFrom(el);
|
|
24864
25061
|
}
|
|
24865
|
-
if (el.hasAttribute("data-ohw-nav-container") || el.hasAttribute("data-ohw-nav-drawer") || isFooterLinksContainer(el)) {
|
|
25062
|
+
if (el.hasAttribute("data-ohw-nav-container") || el.hasAttribute("data-ohw-nav-drawer") || el.hasAttribute("data-ohw-footer-col") || el.hasAttribute("data-ohw-footer-column") || isFooterLinksContainer(el) || isInferredFooterGroup2(el)) {
|
|
24866
25063
|
return getNavigationRoot(el);
|
|
24867
25064
|
}
|
|
24868
25065
|
return null;
|
|
@@ -25084,7 +25281,6 @@ var ICONS = {
|
|
|
25084
25281
|
insertUnorderedList: '<line x1="8" y1="6" x2="21" y2="6"/><line x1="8" y1="12" x2="21" y2="12"/><line x1="8" y1="18" x2="21" y2="18"/><line x1="3" y1="6" x2="3.01" y2="6"/><line x1="3" y1="12" x2="3.01" y2="12"/><line x1="3" y1="18" x2="3.01" y2="18"/>',
|
|
25085
25282
|
insertOrderedList: '<line x1="10" y1="6" x2="21" y2="6"/><line x1="10" y1="12" x2="21" y2="12"/><line x1="10" y1="18" x2="21" y2="18"/><path d="M4 6h1v4"/><path d="M4 10h2"/><path d="M6 18H4c0-1 2-2 2-3s-1-1.5-2-1"/>'
|
|
25086
25283
|
};
|
|
25087
|
-
var HEIGHT_SETTLE_DELAYS = [150, 400, 800];
|
|
25088
25284
|
var SELECTION_CHROME_GAP2 = 4;
|
|
25089
25285
|
var TOOLBAR_STROKE_GAP2 = 4;
|
|
25090
25286
|
var TOOLBAR_OFFSET_FROM_ELEMENT = SELECTION_CHROME_GAP2 + TOOLBAR_STROKE_GAP2;
|
|
@@ -25182,7 +25378,7 @@ function applyVisibleViewport(el, parentScroll) {
|
|
|
25182
25378
|
el.style.top = `${top}px`;
|
|
25183
25379
|
el.style.height = `${height}px`;
|
|
25184
25380
|
}
|
|
25185
|
-
var
|
|
25381
|
+
var TOOLBAR_EDGE_MARGIN4 = 4;
|
|
25186
25382
|
function clampToolbarToClip(top, transform, rect, clip, approxH, gap) {
|
|
25187
25383
|
const isAbove = transform.includes("translateY(-100%)");
|
|
25188
25384
|
let visualTop = isAbove ? top - approxH : top;
|
|
@@ -25209,8 +25405,8 @@ function clampToolbarToClip(top, transform, rect, clip, approxH, gap) {
|
|
|
25209
25405
|
function clampToolbarLeft(centerX, toolbarWidth) {
|
|
25210
25406
|
const half = toolbarWidth / 2;
|
|
25211
25407
|
return Math.max(
|
|
25212
|
-
|
|
25213
|
-
Math.min(centerX, window.innerWidth -
|
|
25408
|
+
TOOLBAR_EDGE_MARGIN4 + half,
|
|
25409
|
+
Math.min(centerX, window.innerWidth - TOOLBAR_EDGE_MARGIN4 - half)
|
|
25214
25410
|
);
|
|
25215
25411
|
}
|
|
25216
25412
|
function calcToolbarPos(rect, parentScroll, toolbarW = 306) {
|
|
@@ -25611,7 +25807,7 @@ function OhhwellsBridge() {
|
|
|
25611
25807
|
}, []);
|
|
25612
25808
|
const subdomainFromQuery = searchParams.get("subdomain");
|
|
25613
25809
|
const [subdomain, setSubdomain] = useState18(() => resolveSubdomain(subdomainFromQuery));
|
|
25614
|
-
|
|
25810
|
+
useLayoutEffect7(() => {
|
|
25615
25811
|
const next = resolveSubdomain(subdomainFromQuery);
|
|
25616
25812
|
if (next !== subdomain) setSubdomain(next);
|
|
25617
25813
|
if (next) return;
|
|
@@ -26090,21 +26286,6 @@ function OhhwellsBridge() {
|
|
|
26090
26286
|
const [isItemDragging, setIsItemDragging] = useState18(false);
|
|
26091
26287
|
const [isFooterFrameSelection, setIsFooterFrameSelection] = useState18(false);
|
|
26092
26288
|
isFooterFrameSelectionRef.current = isFooterFrameSelection;
|
|
26093
|
-
const [floatingPanel, setFloatingPanel] = useState18(null);
|
|
26094
|
-
const floatingPanelOpenRef = useRef14(false);
|
|
26095
|
-
floatingPanelOpenRef.current = floatingPanel !== null;
|
|
26096
|
-
const floatingPanelRef = useRef14(null);
|
|
26097
|
-
floatingPanelRef.current = floatingPanel;
|
|
26098
|
-
const [floatingPanelPos, setFloatingPanelPos] = useState18(null);
|
|
26099
|
-
const buttonCollectionDragRef = useRef14(null);
|
|
26100
|
-
const buttonDropInsertIndexRef = useRef14(null);
|
|
26101
|
-
const [buttonDropSlots, setButtonDropSlots] = useState18([]);
|
|
26102
|
-
const [activeButtonDropIndex, setActiveButtonDropIndex] = useState18(null);
|
|
26103
|
-
const buttonPointerDragRef = useRef14(null);
|
|
26104
|
-
const [buttonStyleTick, setButtonStyleTick] = useState18(0);
|
|
26105
|
-
const [logoSizeDraft, setLogoSizeDraft] = useState18(null);
|
|
26106
|
-
const [editorViewport, setEditorViewport] = useState18("desktop");
|
|
26107
|
-
const [parentScrollSnap, setParentScrollSnap] = useState18(null);
|
|
26108
26289
|
const [navDropdownPreviewOpen, setNavDropdownPreviewOpen] = useState18(null);
|
|
26109
26290
|
const [footerHeadingVisible, setFooterHeadingVisible] = useState18(null);
|
|
26110
26291
|
const footerDragRef = useRef14(null);
|
|
@@ -26130,6 +26311,21 @@ function OhhwellsBridge() {
|
|
|
26130
26311
|
const stylesRef = useRef14("");
|
|
26131
26312
|
const appliedDrawerRef = useRef14(null);
|
|
26132
26313
|
const pendingDeleteUndoRef = useRef14(null);
|
|
26314
|
+
const [floatingPanel, setFloatingPanel] = useState18(null);
|
|
26315
|
+
const floatingPanelOpenRef = useRef14(false);
|
|
26316
|
+
const floatingPanelRef = useRef14(null);
|
|
26317
|
+
floatingPanelRef.current = floatingPanel;
|
|
26318
|
+
const setFloatingPanelRef = useRef14(setFloatingPanel);
|
|
26319
|
+
const [floatingPanelPos, setFloatingPanelPos] = useState18(null);
|
|
26320
|
+
const buttonCollectionDragRef = useRef14(null);
|
|
26321
|
+
const buttonDropInsertIndexRef = useRef14(null);
|
|
26322
|
+
const [buttonDropSlots, setButtonDropSlots] = useState18([]);
|
|
26323
|
+
const [activeButtonDropIndex, setActiveButtonDropIndex] = useState18(null);
|
|
26324
|
+
const buttonPointerDragRef = useRef14(null);
|
|
26325
|
+
const [buttonStyleTick, setButtonStyleTick] = useState18(0);
|
|
26326
|
+
const [logoSizeDraft, setLogoSizeDraft] = useState18(null);
|
|
26327
|
+
const [editorViewport, setEditorViewport] = useState18("desktop");
|
|
26328
|
+
const [parentScrollSnap, setParentScrollSnap] = useState18(null);
|
|
26133
26329
|
const [sitePages, setSitePages] = useState18([]);
|
|
26134
26330
|
const collectionItemsRef = useRef14(/* @__PURE__ */ new Map());
|
|
26135
26331
|
const [sectionsByPath, setSectionsByPath] = useState18({});
|
|
@@ -26139,7 +26335,18 @@ function OhhwellsBridge() {
|
|
|
26139
26335
|
const linkPopoverOpenRef = useRef14(false);
|
|
26140
26336
|
const linkPopoverGraceUntilRef = useRef14(0);
|
|
26141
26337
|
setLinkPopoverRef.current = setLinkPopover;
|
|
26338
|
+
setFloatingPanelRef.current = setFloatingPanel;
|
|
26142
26339
|
linkPopoverSessionRef.current = linkPopover;
|
|
26340
|
+
floatingPanelOpenRef.current = Boolean(floatingPanel);
|
|
26341
|
+
useEffect17(() => {
|
|
26342
|
+
const syncViewport = () => {
|
|
26343
|
+
const next = window.innerWidth <= 480 ? "mobile" : "desktop";
|
|
26344
|
+
setEditorViewport((prev) => prev === next ? prev : next);
|
|
26345
|
+
};
|
|
26346
|
+
syncViewport();
|
|
26347
|
+
window.addEventListener("resize", syncViewport);
|
|
26348
|
+
return () => window.removeEventListener("resize", syncViewport);
|
|
26349
|
+
}, []);
|
|
26143
26350
|
useEffect17(() => {
|
|
26144
26351
|
setSectionOrderPersistHandler((entries) => {
|
|
26145
26352
|
const currentPath = window.location.pathname;
|
|
@@ -26288,6 +26495,43 @@ function OhhwellsBridge() {
|
|
|
26288
26495
|
if (!useFixtures) postToParent2({ type: "ow:request-site-pages" });
|
|
26289
26496
|
return () => window.removeEventListener("message", onSitePages);
|
|
26290
26497
|
}, [isEditMode, postToParent2]);
|
|
26498
|
+
useEffect17(() => {
|
|
26499
|
+
if (!isEditMode) return;
|
|
26500
|
+
const deps = {
|
|
26501
|
+
getEditContent: () => editContentRef.current,
|
|
26502
|
+
setEditContent: (next) => {
|
|
26503
|
+
editContentRef.current = next;
|
|
26504
|
+
},
|
|
26505
|
+
applyLinkByKey,
|
|
26506
|
+
postToParent: postToParent2
|
|
26507
|
+
};
|
|
26508
|
+
const onPageMessage = (e) => {
|
|
26509
|
+
if (e.data?.type === "ow:page-created") {
|
|
26510
|
+
const { path, title } = e.data;
|
|
26511
|
+
if (typeof path !== "string" || !path) return;
|
|
26512
|
+
if (addNavLinkForPage({ path, title: typeof title === "string" && title ? title : path }, deps)) {
|
|
26513
|
+
enforceLinkHrefs();
|
|
26514
|
+
}
|
|
26515
|
+
return;
|
|
26516
|
+
}
|
|
26517
|
+
if (e.data?.type === "ow:page-renamed") {
|
|
26518
|
+
const { oldPath, newPath, oldTitle, newTitle } = e.data;
|
|
26519
|
+
if (typeof oldPath !== "string" || typeof newPath !== "string") return;
|
|
26520
|
+
const moved = retargetPageLinks(
|
|
26521
|
+
{
|
|
26522
|
+
oldPath,
|
|
26523
|
+
newPath,
|
|
26524
|
+
oldTitle: typeof oldTitle === "string" ? oldTitle : void 0,
|
|
26525
|
+
newTitle: typeof newTitle === "string" ? newTitle : void 0
|
|
26526
|
+
},
|
|
26527
|
+
deps
|
|
26528
|
+
);
|
|
26529
|
+
if (moved > 0) enforceLinkHrefs();
|
|
26530
|
+
}
|
|
26531
|
+
};
|
|
26532
|
+
window.addEventListener("message", onPageMessage);
|
|
26533
|
+
return () => window.removeEventListener("message", onPageMessage);
|
|
26534
|
+
}, [isEditMode, postToParent2]);
|
|
26291
26535
|
useEffect17(() => {
|
|
26292
26536
|
if (!isEditMode || shouldUseDevFixtures()) return;
|
|
26293
26537
|
void loadAllSectionsManifest().then((manifest) => {
|
|
@@ -27809,7 +28053,7 @@ function OhhwellsBridge() {
|
|
|
27809
28053
|
isFooterFrameSelection,
|
|
27810
28054
|
postToParent2
|
|
27811
28055
|
]);
|
|
27812
|
-
|
|
28056
|
+
useLayoutEffect7(() => {
|
|
27813
28057
|
if (!subdomain || isEditMode) {
|
|
27814
28058
|
setFetchState("done");
|
|
27815
28059
|
return;
|
|
@@ -27836,6 +28080,7 @@ function OhhwellsBridge() {
|
|
|
27836
28080
|
applyAiFooterFromContent(content);
|
|
27837
28081
|
if (typeof content[STYLE_STORE_KEY] === "string") {
|
|
27838
28082
|
stylesRef.current = content[STYLE_STORE_KEY];
|
|
28083
|
+
document.querySelectorAll('[data-ohw-editable="form"]').forEach((f) => markFormFields(f));
|
|
27839
28084
|
applyStylesToDom(parseStyleStore(content[STYLE_STORE_KEY]));
|
|
27840
28085
|
}
|
|
27841
28086
|
applyBrandChrome(content);
|
|
@@ -27846,12 +28091,12 @@ function OhhwellsBridge() {
|
|
|
27846
28091
|
if (key === "__ohw_sections") continue;
|
|
27847
28092
|
if (key === AI_SECTIONS_KEY) continue;
|
|
27848
28093
|
if (key === AI_FOOTER_KEY) continue;
|
|
28094
|
+
if (key === LOGO_PLACEHOLDER_KEY) continue;
|
|
28095
|
+
if (LOGO_IMAGE_KEYS.includes(key)) continue;
|
|
27849
28096
|
if (key === BRAND_KIT_KEY) continue;
|
|
27850
28097
|
if (key === STYLE_STORE_KEY) continue;
|
|
27851
28098
|
if (BRAND_CHROME_KEYS.has(key)) continue;
|
|
27852
|
-
if (key === LOGO_PLACEHOLDER_KEY) continue;
|
|
27853
28099
|
if (key === CUSTOM_CODE_AFTER_HEAD_KEY || key === CUSTOM_CODE_BEFORE_HEAD_KEY) continue;
|
|
27854
|
-
if (LOGO_IMAGE_KEYS.includes(key)) continue;
|
|
27855
28100
|
if (typeof content[AI_FOOTER_KEY] === "string" && content[AI_FOOTER_KEY] && isAiFooterOwnedContentKey(key)) {
|
|
27856
28101
|
continue;
|
|
27857
28102
|
}
|
|
@@ -28082,17 +28327,18 @@ function OhhwellsBridge() {
|
|
|
28082
28327
|
}
|
|
28083
28328
|
applyAiFooterFromContent(content);
|
|
28084
28329
|
if (typeof content[STYLE_STORE_KEY] === "string") {
|
|
28330
|
+
document.querySelectorAll('[data-ohw-editable="form"]').forEach((f) => markFormFields(f));
|
|
28085
28331
|
applyStylesToDom(parseStyleStore(content[STYLE_STORE_KEY]));
|
|
28086
28332
|
}
|
|
28087
28333
|
for (const [key, val] of Object.entries(content)) {
|
|
28088
28334
|
if (key === "__ohw_sections") continue;
|
|
28089
28335
|
if (key === AI_SECTIONS_KEY) continue;
|
|
28090
28336
|
if (key === AI_FOOTER_KEY) continue;
|
|
28337
|
+
if (key === LOGO_PLACEHOLDER_KEY) continue;
|
|
28338
|
+
if (LOGO_IMAGE_KEYS.includes(key)) continue;
|
|
28091
28339
|
if (key === BRAND_KIT_KEY) continue;
|
|
28092
28340
|
if (key === STYLE_STORE_KEY) continue;
|
|
28093
28341
|
if (BRAND_CHROME_KEYS.has(key)) continue;
|
|
28094
|
-
if (key === LOGO_PLACEHOLDER_KEY) continue;
|
|
28095
|
-
if (LOGO_IMAGE_KEYS.includes(key)) continue;
|
|
28096
28342
|
if (typeof content[AI_FOOTER_KEY] === "string" && content[AI_FOOTER_KEY] && isAiFooterOwnedContentKey(key)) {
|
|
28097
28343
|
continue;
|
|
28098
28344
|
}
|
|
@@ -28175,7 +28421,7 @@ function OhhwellsBridge() {
|
|
|
28175
28421
|
if (debounceTimer) clearTimeout(debounceTimer);
|
|
28176
28422
|
};
|
|
28177
28423
|
}, [subdomain, isEditMode, pathname]);
|
|
28178
|
-
|
|
28424
|
+
useLayoutEffect7(() => {
|
|
28179
28425
|
const el = document.getElementById("ohw-loader");
|
|
28180
28426
|
if (!el) return;
|
|
28181
28427
|
const visible = Boolean(subdomain) && fetchState !== "done";
|
|
@@ -28359,26 +28605,11 @@ function OhhwellsBridge() {
|
|
|
28359
28605
|
const t2 = setTimeout(measure, 500);
|
|
28360
28606
|
const ro = new ResizeObserver(schedule);
|
|
28361
28607
|
ro.observe(document.body);
|
|
28362
|
-
let lastWidth = window.innerWidth;
|
|
28363
|
-
let resizeTimers = [];
|
|
28364
|
-
const clearResizeTimers = () => {
|
|
28365
|
-
resizeTimers.forEach(clearTimeout);
|
|
28366
|
-
resizeTimers = [];
|
|
28367
|
-
};
|
|
28368
|
-
const handleResize = () => {
|
|
28369
|
-
if (window.innerWidth === lastWidth) return;
|
|
28370
|
-
lastWidth = window.innerWidth;
|
|
28371
|
-
clearResizeTimers();
|
|
28372
|
-
resizeTimers = HEIGHT_SETTLE_DELAYS.map((delay) => setTimeout(measure, delay));
|
|
28373
|
-
};
|
|
28374
|
-
window.addEventListener("resize", handleResize);
|
|
28375
28608
|
return () => {
|
|
28376
28609
|
clearTimeout(t1);
|
|
28377
28610
|
clearTimeout(t2);
|
|
28378
28611
|
if (raf != null) cancelAnimationFrame(raf);
|
|
28379
28612
|
ro.disconnect();
|
|
28380
|
-
clearResizeTimers();
|
|
28381
|
-
window.removeEventListener("resize", handleResize);
|
|
28382
28613
|
};
|
|
28383
28614
|
}, [pathname, isEditMode, postToParent2]);
|
|
28384
28615
|
useEffect17(() => {
|
|
@@ -28675,6 +28906,13 @@ function OhhwellsBridge() {
|
|
|
28675
28906
|
if (target.closest("[data-ohw-state-toggle]")) return;
|
|
28676
28907
|
if (target.closest("[data-ohw-max-badge]")) return;
|
|
28677
28908
|
if (isInsideLinkEditor(target)) return;
|
|
28909
|
+
if (isInsideFloatingPanel(target)) return;
|
|
28910
|
+
if (target.closest("[data-ohw-form-toolbar]")) return;
|
|
28911
|
+
if (target.closest(
|
|
28912
|
+
'[data-ohw-field-toolbar], [data-ohw-field-type-picker], [data-radix-popper-content-wrapper], [role="menu"], [data-slot="dropdown-menu-content"]'
|
|
28913
|
+
)) {
|
|
28914
|
+
return;
|
|
28915
|
+
}
|
|
28678
28916
|
if (selectedMediaElRef.current && !selectedMediaElRef.current.contains(target) && !target.closest("[data-ohw-media-overlay], [data-ohw-edit-chrome], [data-ohw-item-interaction]")) {
|
|
28679
28917
|
clearMediaSelectionRef.current();
|
|
28680
28918
|
}
|
|
@@ -28698,8 +28936,6 @@ function OhhwellsBridge() {
|
|
|
28698
28936
|
return;
|
|
28699
28937
|
}
|
|
28700
28938
|
}
|
|
28701
|
-
if (isInsideFloatingPanel(target)) return;
|
|
28702
|
-
if (target.closest("[data-ohw-form-toolbar]")) return;
|
|
28703
28939
|
const collectionItem = matchCollectionItemClick(target, collectionItemsRef.current);
|
|
28704
28940
|
if (collectionItem) {
|
|
28705
28941
|
e.preventDefault();
|
|
@@ -28711,11 +28947,6 @@ function OhhwellsBridge() {
|
|
|
28711
28947
|
});
|
|
28712
28948
|
return;
|
|
28713
28949
|
}
|
|
28714
|
-
if (target.closest(
|
|
28715
|
-
'[data-ohw-field-toolbar], [data-ohw-field-type-picker], [data-radix-popper-content-wrapper], [role="menu"], [data-slot="dropdown-menu-content"]'
|
|
28716
|
-
)) {
|
|
28717
|
-
return;
|
|
28718
|
-
}
|
|
28719
28950
|
{
|
|
28720
28951
|
const formEl = getFormElement(target);
|
|
28721
28952
|
const onSuccessText = target.closest(`[${SUCCESS_TEXT_ATTR}]`);
|
|
@@ -28869,9 +29100,13 @@ function OhhwellsBridge() {
|
|
|
28869
29100
|
if (isIconEditable(editable) && !getSocialItem(editable)) {
|
|
28870
29101
|
e.preventDefault();
|
|
28871
29102
|
e.stopPropagation();
|
|
28872
|
-
selectIconElementRef.current(editable);
|
|
28873
29103
|
const aiIcon = editable.hasAttribute("data-ai-icon");
|
|
28874
29104
|
const featureIcon = aiIcon && /\.features\.\d+\.icon$/.test(editable.dataset.ohwKey ?? "");
|
|
29105
|
+
if (aiIcon) {
|
|
29106
|
+
aiSectionApiRef.current?.selectFromElement(editable);
|
|
29107
|
+
} else {
|
|
29108
|
+
selectIconElementRef.current(editable);
|
|
29109
|
+
}
|
|
28875
29110
|
postToParentRef.current({
|
|
28876
29111
|
type: "ow:icon-pick",
|
|
28877
29112
|
key: editable.dataset.ohwKey ?? "",
|
|
@@ -29099,6 +29334,9 @@ function OhhwellsBridge() {
|
|
|
29099
29334
|
setHoveredItemRect(null);
|
|
29100
29335
|
hoveredNavContainerRef.current = null;
|
|
29101
29336
|
setHoveredNavContainerRect(null);
|
|
29337
|
+
siblingHintElRef.current = null;
|
|
29338
|
+
setSiblingHintRect(null);
|
|
29339
|
+
setSiblingHintRects([]);
|
|
29102
29340
|
return;
|
|
29103
29341
|
}
|
|
29104
29342
|
{
|
|
@@ -29219,7 +29457,6 @@ function OhhwellsBridge() {
|
|
|
29219
29457
|
hoveredNavContainerRef.current = null;
|
|
29220
29458
|
setHoveredNavContainerRect(null);
|
|
29221
29459
|
hoveredItemElRef.current = editable;
|
|
29222
|
-
setHoveredItemRect(isSelectedForHoverRef.current(editable) ? null : editable.getBoundingClientRect());
|
|
29223
29460
|
}
|
|
29224
29461
|
}
|
|
29225
29462
|
}
|
|
@@ -29929,7 +30166,11 @@ function OhhwellsBridge() {
|
|
|
29929
30166
|
};
|
|
29930
30167
|
const handleMouseMove = (e) => {
|
|
29931
30168
|
const { clientX, clientY } = e;
|
|
29932
|
-
if (pointOwnedByFloatingPanel(clientX, clientY))
|
|
30169
|
+
if (pointOwnedByFloatingPanel(clientX, clientY)) {
|
|
30170
|
+
dismissImageHover();
|
|
30171
|
+
clearImageHover();
|
|
30172
|
+
return;
|
|
30173
|
+
}
|
|
29933
30174
|
if (isNavDrawerOpen() && isPointOutsideOpenDrawer(clientX, clientY)) {
|
|
29934
30175
|
document.querySelectorAll("[data-ohw-hovered]").forEach((el) => el.removeAttribute("data-ohw-hovered"));
|
|
29935
30176
|
formHoverElRef.current = null;
|
|
@@ -29958,7 +30199,12 @@ function OhhwellsBridge() {
|
|
|
29958
30199
|
setHoveredItemRect(null);
|
|
29959
30200
|
hoveredNavContainerRef.current = null;
|
|
29960
30201
|
setHoveredNavContainerRect(null);
|
|
30202
|
+
siblingHintElRef.current = null;
|
|
30203
|
+
setSiblingHintRect(null);
|
|
30204
|
+
setSiblingHintRects([]);
|
|
29961
30205
|
dismissImageHover();
|
|
30206
|
+
clearImageHover();
|
|
30207
|
+
setSectionGap(null);
|
|
29962
30208
|
return;
|
|
29963
30209
|
}
|
|
29964
30210
|
if (probeSocialsRowAt(clientX, clientY)) return;
|
|
@@ -29970,7 +30216,11 @@ function OhhwellsBridge() {
|
|
|
29970
30216
|
if (e.data?.type !== "ow:pointer-sync") return;
|
|
29971
30217
|
const { clientX, clientY } = e.data;
|
|
29972
30218
|
if (typeof clientX !== "number" || typeof clientY !== "number") return;
|
|
29973
|
-
if (pointOwnedByFloatingPanel(clientX, clientY))
|
|
30219
|
+
if (pointOwnedByFloatingPanel(clientX, clientY)) {
|
|
30220
|
+
dismissImageHover();
|
|
30221
|
+
clearImageHover();
|
|
30222
|
+
return;
|
|
30223
|
+
}
|
|
29974
30224
|
if (isNavDrawerOpen() && isPointOutsideOpenDrawer(clientX, clientY)) return;
|
|
29975
30225
|
if (probeSocialsRowAt(clientX, clientY)) return;
|
|
29976
30226
|
probeSectionGapAt(clientX, clientY);
|
|
@@ -30350,6 +30600,7 @@ function OhhwellsBridge() {
|
|
|
30350
30600
|
applyAiFooterFromContent(content);
|
|
30351
30601
|
if (typeof content[STYLE_STORE_KEY] === "string") {
|
|
30352
30602
|
stylesRef.current = content[STYLE_STORE_KEY];
|
|
30603
|
+
document.querySelectorAll('[data-ohw-editable="form"]').forEach((f) => markFormFields(f));
|
|
30353
30604
|
applyStylesToDom(parseStyleStore(content[STYLE_STORE_KEY]));
|
|
30354
30605
|
}
|
|
30355
30606
|
applyBrandChrome(content);
|
|
@@ -30364,12 +30615,12 @@ function OhhwellsBridge() {
|
|
|
30364
30615
|
}
|
|
30365
30616
|
if (key === AI_SECTIONS_KEY) continue;
|
|
30366
30617
|
if (key === AI_FOOTER_KEY) continue;
|
|
30618
|
+
if (key === LOGO_PLACEHOLDER_KEY) continue;
|
|
30619
|
+
if (LOGO_IMAGE_KEYS.includes(key) && !String(val ?? "").trim()) continue;
|
|
30367
30620
|
if (key === BRAND_KIT_KEY) continue;
|
|
30368
30621
|
if (key === STYLE_STORE_KEY) continue;
|
|
30369
30622
|
if (BRAND_CHROME_KEYS.has(key)) continue;
|
|
30370
|
-
if (key === LOGO_PLACEHOLDER_KEY) continue;
|
|
30371
30623
|
if (key === CUSTOM_CODE_AFTER_HEAD_KEY || key === CUSTOM_CODE_BEFORE_HEAD_KEY) continue;
|
|
30372
|
-
if (LOGO_IMAGE_KEYS.includes(key) && !String(val ?? "").trim()) continue;
|
|
30373
30624
|
if (typeof content[AI_FOOTER_KEY] === "string" && content[AI_FOOTER_KEY] && isAiFooterOwnedContentKey(key)) {
|
|
30374
30625
|
continue;
|
|
30375
30626
|
}
|
|
@@ -31005,6 +31256,12 @@ function OhhwellsBridge() {
|
|
|
31005
31256
|
closeLinkPopoverRef.current();
|
|
31006
31257
|
return;
|
|
31007
31258
|
}
|
|
31259
|
+
if (floatingPanelOpenRef.current) {
|
|
31260
|
+
setFloatingPanelRef.current(null);
|
|
31261
|
+
deselectRef.current();
|
|
31262
|
+
deactivateRef.current();
|
|
31263
|
+
return;
|
|
31264
|
+
}
|
|
31008
31265
|
deselectRef.current();
|
|
31009
31266
|
deactivateRef.current();
|
|
31010
31267
|
clearMediaSelectionRef.current();
|
|
@@ -31393,7 +31650,7 @@ function OhhwellsBridge() {
|
|
|
31393
31650
|
const sectionEl = foundEl && !foundEl.hasAttribute("data-ohw-ai-template-hidden") && !foundEl.hasAttribute("data-ohw-ai-removed") && !foundEl.hasAttribute("data-ohw-ai-replaced-by") ? foundEl : null;
|
|
31394
31651
|
const nodes = sectionEl ? collectEditableNodes(void 0, sectionEl).filter(
|
|
31395
31652
|
(n) => n.key && !n.key.startsWith("__ohw_") && !["meta", "sections", "video-setting"].includes(n.type)
|
|
31396
|
-
).map((n) => ({ ...n, text: n.text ?? "", type: normalizeAiNodeType(n.type) })) : [];
|
|
31653
|
+
).map((n) => ({ ...n, text: n.text ?? "", type: normalizeAiNodeType(n.type) })).map((n) => withNodeFontSize(n, sectionEl)) : [];
|
|
31397
31654
|
const items = sectionEl ? collectItemGroups(sectionEl) : [];
|
|
31398
31655
|
const box = sectionEl?.getBoundingClientRect();
|
|
31399
31656
|
const rect = box ? {
|
|
@@ -31840,10 +32097,10 @@ function OhhwellsBridge() {
|
|
|
31840
32097
|
window.removeEventListener("message", handleDuplicateSection);
|
|
31841
32098
|
window.removeEventListener("message", handleDeactivate);
|
|
31842
32099
|
window.removeEventListener("message", handleSelectNav);
|
|
31843
|
-
document.documentElement.removeAttribute("data-ohw-panel-dragging");
|
|
31844
32100
|
window.removeEventListener("message", handleToastAction);
|
|
31845
32101
|
window.removeEventListener("message", handleFormCount);
|
|
31846
32102
|
window.removeEventListener("message", handleUiEscape);
|
|
32103
|
+
document.documentElement.removeAttribute("data-ohw-panel-dragging");
|
|
31847
32104
|
autoSaveTimers.current.forEach(clearTimeout);
|
|
31848
32105
|
autoSaveTimers.current.clear();
|
|
31849
32106
|
if (imageUnhoverTimerRef.current) clearTimeout(imageUnhoverTimerRef.current);
|
|
@@ -32137,7 +32394,7 @@ function OhhwellsBridge() {
|
|
|
32137
32394
|
postToParent2({
|
|
32138
32395
|
type: "ow:ready",
|
|
32139
32396
|
version: "1",
|
|
32140
|
-
bridgeVersion: "0.1.
|
|
32397
|
+
bridgeVersion: "0.1.160-next.427",
|
|
32141
32398
|
path: pathname,
|
|
32142
32399
|
nodes: collectEditableNodes(editContentRef.current),
|
|
32143
32400
|
sections
|
|
@@ -32872,7 +33129,7 @@ function OhhwellsBridge() {
|
|
|
32872
33129
|
className: "flex h-7 w-7 items-center justify-center rounded-md text-foreground transition-colors hover:bg-muted/80",
|
|
32873
33130
|
onClick: () => setFieldTypePickerOpen((open) => !open),
|
|
32874
33131
|
"data-ohw-add-field": "",
|
|
32875
|
-
children: /* @__PURE__ */ jsx40(
|
|
33132
|
+
children: /* @__PURE__ */ jsx40(Plus6, { size: 15, "aria-hidden": true })
|
|
32876
33133
|
}
|
|
32877
33134
|
),
|
|
32878
33135
|
/* @__PURE__ */ jsx40("div", { className: "mx-0.5 h-5 w-px bg-border" }),
|