@ohhwells/bridge 0.1.158 → 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 +1134 -722
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +58 -1
- package/dist/index.d.ts +58 -1
- package/dist/index.js +1171 -743
- package/dist/index.js.map +1 -1
- package/dist/pages.cjs +9 -1
- package/dist/pages.cjs.map +1 -1
- package/dist/pages.d.cts +2 -0
- package/dist/pages.d.ts +2 -0
- package/dist/pages.js +9 -1
- package/dist/pages.js.map +1 -1
- package/dist/styles.css +116 -0
- package/package.json +3 -3
package/dist/index.cjs
CHANGED
|
@@ -220,6 +220,56 @@ function isRenderableTree(value) {
|
|
|
220
220
|
return AI_TREE_SCHEMA_VERSIONS.includes(tree.schemaVersion) && tree.type === "section" && Array.isArray(tree.rows);
|
|
221
221
|
}
|
|
222
222
|
|
|
223
|
+
// src/lib/headline-size.ts
|
|
224
|
+
var HEADLINE_SIZE_MULTIPLIERS = {
|
|
225
|
+
xs: 0.7,
|
|
226
|
+
sm: 0.85,
|
|
227
|
+
base: 1,
|
|
228
|
+
lg: 1.2,
|
|
229
|
+
xl: 1.45,
|
|
230
|
+
"2xl": 1.75
|
|
231
|
+
};
|
|
232
|
+
var HEADLINE_SIZE_ATTR = "data-ohw-style-headlinesize";
|
|
233
|
+
var PREV_ATTR = "data-ohw-style-prev-fsmul";
|
|
234
|
+
var NODE_FONT_SIZE_ATTR = "data-ohw-style-prev-font-size";
|
|
235
|
+
function headingsIn(section) {
|
|
236
|
+
return Array.from(section.querySelectorAll("h1, h2, h3"));
|
|
237
|
+
}
|
|
238
|
+
function clearHeadlineSizes(root = document) {
|
|
239
|
+
for (const el of Array.from(root.querySelectorAll(`[${PREV_ATTR}]`))) {
|
|
240
|
+
const prev = el.getAttribute(PREV_ATTR) ?? "";
|
|
241
|
+
if (prev) el.style.setProperty("font-size", prev);
|
|
242
|
+
else el.style.removeProperty("font-size");
|
|
243
|
+
el.removeAttribute(PREV_ATTR);
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
function applyHeadlineSizes(root = document) {
|
|
247
|
+
clearHeadlineSizes(root);
|
|
248
|
+
for (const section of Array.from(
|
|
249
|
+
root.querySelectorAll(`[${HEADLINE_SIZE_ATTR}]`)
|
|
250
|
+
)) {
|
|
251
|
+
const multiplier = HEADLINE_SIZE_MULTIPLIERS[section.getAttribute(HEADLINE_SIZE_ATTR) ?? ""];
|
|
252
|
+
if (!multiplier || multiplier === 1) continue;
|
|
253
|
+
for (const heading of headingsIn(section)) {
|
|
254
|
+
if (heading.hasAttribute(NODE_FONT_SIZE_ATTR)) continue;
|
|
255
|
+
const base = Number.parseFloat(window.getComputedStyle(heading).fontSize);
|
|
256
|
+
if (!Number.isFinite(base) || base <= 0) continue;
|
|
257
|
+
heading.setAttribute(PREV_ATTR, heading.style.getPropertyValue("font-size"));
|
|
258
|
+
heading.style.setProperty("font-size", `${Math.round(base * multiplier * 100) / 100}px`, "important");
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
var resizeInstalled = false;
|
|
263
|
+
function installHeadlineSizeResize() {
|
|
264
|
+
if (resizeInstalled || typeof window === "undefined") return;
|
|
265
|
+
resizeInstalled = true;
|
|
266
|
+
let timer;
|
|
267
|
+
window.addEventListener("resize", () => {
|
|
268
|
+
if (timer) clearTimeout(timer);
|
|
269
|
+
timer = setTimeout(() => applyHeadlineSizes(), 120);
|
|
270
|
+
});
|
|
271
|
+
}
|
|
272
|
+
|
|
223
273
|
// src/lib/sections.ts
|
|
224
274
|
var LINK_PICKER_EXCLUDED_IDS = /* @__PURE__ */ new Set(["navbar", "footer"]);
|
|
225
275
|
function isChromeSection(el) {
|
|
@@ -6011,6 +6061,7 @@ var SECTION_ATTRS = {
|
|
|
6011
6061
|
sectionBackground: "data-ohw-style-bg",
|
|
6012
6062
|
textDistribution: "data-ohw-style-distribution",
|
|
6013
6063
|
headlineScale: "data-ohw-style-headline",
|
|
6064
|
+
headlineSize: HEADLINE_SIZE_ATTR,
|
|
6014
6065
|
imageAspect: "data-ohw-style-aspect",
|
|
6015
6066
|
spacing: "data-ohw-style-spacing",
|
|
6016
6067
|
verticalPadding: "data-ohw-style-vpadding",
|
|
@@ -6079,6 +6130,15 @@ function clearSectionAttrs(root) {
|
|
|
6079
6130
|
}
|
|
6080
6131
|
}
|
|
6081
6132
|
var ITEM_WROTE_ATTR = "data-ohw-style-item";
|
|
6133
|
+
function paintIcon(slot, color) {
|
|
6134
|
+
for (const el of [slot, ...Array.from(slot.querySelectorAll("svg, svg *"))]) {
|
|
6135
|
+
const styled = el;
|
|
6136
|
+
if (!styled.style) continue;
|
|
6137
|
+
saveInline(styled, "color");
|
|
6138
|
+
styled.style.setProperty("color", color, "important");
|
|
6139
|
+
styled.setAttribute(NODE_WROTE_ATTR, "");
|
|
6140
|
+
}
|
|
6141
|
+
}
|
|
6082
6142
|
function clearNodeProps(root) {
|
|
6083
6143
|
for (const el of Array.from(root.querySelectorAll(`[${NODE_WROTE_ATTR}]`))) {
|
|
6084
6144
|
const h = el;
|
|
@@ -6116,6 +6176,7 @@ function applyStylesToDom(store) {
|
|
|
6116
6176
|
ensureStyleSheet();
|
|
6117
6177
|
clearSectionAttrs(document);
|
|
6118
6178
|
clearNodeProps(document);
|
|
6179
|
+
clearHeadlineSizes(document);
|
|
6119
6180
|
loadStyleFonts(
|
|
6120
6181
|
store ? [
|
|
6121
6182
|
...Object.values(store.nodes).flatMap((n) => n.fontFamily ? [n.fontFamily] : []),
|
|
@@ -6189,9 +6250,13 @@ function applyStylesToDom(store) {
|
|
|
6189
6250
|
const nodes = document.querySelectorAll(`[data-ohw-key="${CSS.escape(key)}"]`);
|
|
6190
6251
|
for (const el of Array.from(nodes)) {
|
|
6191
6252
|
if (override.color !== void 0) {
|
|
6192
|
-
|
|
6193
|
-
|
|
6194
|
-
|
|
6253
|
+
if (el.dataset.ohwEditable === "icon") {
|
|
6254
|
+
paintIcon(el, override.color);
|
|
6255
|
+
} else {
|
|
6256
|
+
saveInline(el, "color");
|
|
6257
|
+
el.style.setProperty("color", override.color, "important");
|
|
6258
|
+
el.setAttribute(NODE_WROTE_ATTR, "");
|
|
6259
|
+
}
|
|
6195
6260
|
}
|
|
6196
6261
|
if (override.fontFamily !== void 0) {
|
|
6197
6262
|
saveInline(el, "font-family");
|
|
@@ -6248,6 +6313,18 @@ function applyStylesToDom(store) {
|
|
|
6248
6313
|
}
|
|
6249
6314
|
}
|
|
6250
6315
|
}
|
|
6316
|
+
for (const [sectionId, override] of Object.entries(store.sections)) {
|
|
6317
|
+
if (override.iconColor === void 0) continue;
|
|
6318
|
+
const escaped = CSS.escape(sectionId);
|
|
6319
|
+
const byInstance = document.querySelectorAll(`[data-ohw-instance="${escaped}"]`);
|
|
6320
|
+
const sections = byInstance.length ? byInstance : document.querySelectorAll(`[data-ohw-section="${escaped}"]`);
|
|
6321
|
+
for (const marker of Array.from(sections)) {
|
|
6322
|
+
const icons = marker.querySelectorAll('[data-ohw-editable="icon"]');
|
|
6323
|
+
for (const el of Array.from(icons)) paintIcon(el, override.iconColor);
|
|
6324
|
+
}
|
|
6325
|
+
}
|
|
6326
|
+
applyHeadlineSizes(document);
|
|
6327
|
+
installHeadlineSizeResize();
|
|
6251
6328
|
}
|
|
6252
6329
|
|
|
6253
6330
|
// src/lib/ai-sections-store.ts
|
|
@@ -6287,17 +6364,21 @@ function resolveSectionTree(sectionId, aiSectionsRaw) {
|
|
|
6287
6364
|
return parseAiSectionsState(aiSectionsRaw).sections.find((entry) => entry.id === sectionId)?.tree;
|
|
6288
6365
|
}
|
|
6289
6366
|
function resolveSectionSettingsContext(sectionId, aiSectionsRaw, stylesRaw) {
|
|
6367
|
+
const styleOverride = parseStyleStore(stylesRaw)?.sections[sectionId];
|
|
6368
|
+
const headlineSize = styleOverride?.headlineSize;
|
|
6290
6369
|
const genSettings = parseAiSectionsState(aiSectionsRaw).sections.find(
|
|
6291
6370
|
(entry) => entry.id === sectionId
|
|
6292
6371
|
)?.tree.settings;
|
|
6293
|
-
if (genSettings)
|
|
6294
|
-
|
|
6295
|
-
|
|
6372
|
+
if (genSettings) {
|
|
6373
|
+
return { ...genSettings, ...headlineSize ? { headlineSize } : {} };
|
|
6374
|
+
}
|
|
6375
|
+
if (!styleOverride?.verticalPadding && !styleOverride?.minHeight && !styleOverride?.spacing && !headlineSize) {
|
|
6296
6376
|
return void 0;
|
|
6297
6377
|
}
|
|
6298
6378
|
return {
|
|
6299
|
-
verticalPadding: styleOverride
|
|
6300
|
-
minHeight: styleOverride
|
|
6379
|
+
verticalPadding: styleOverride?.verticalPadding ?? legacyVerticalPaddingAlias(styleOverride?.spacing),
|
|
6380
|
+
minHeight: styleOverride?.minHeight,
|
|
6381
|
+
...headlineSize ? { headlineSize } : {}
|
|
6301
6382
|
};
|
|
6302
6383
|
}
|
|
6303
6384
|
function applyTreeToState(state, payload) {
|
|
@@ -6682,6 +6763,21 @@ function pricingCardFeatureCount(tree, index) {
|
|
|
6682
6763
|
const target = findPricingCollection(tree)?.children?.[index];
|
|
6683
6764
|
return target ? pricingFeatureList(target).length : 0;
|
|
6684
6765
|
}
|
|
6766
|
+
function prevailingFeatureIcon(features) {
|
|
6767
|
+
const counts = /* @__PURE__ */ new Map();
|
|
6768
|
+
for (const row of features) {
|
|
6769
|
+
const key = `${row.icon ?? ""}|${row.iconColor ?? ""}`;
|
|
6770
|
+
const entry = counts.get(key) ?? { count: 0, ...row.icon ? { icon: row.icon } : {}, ...row.iconColor ? { iconColor: row.iconColor } : {} };
|
|
6771
|
+
entry.count += 1;
|
|
6772
|
+
counts.set(key, entry);
|
|
6773
|
+
}
|
|
6774
|
+
let best = null;
|
|
6775
|
+
for (const entry of counts.values()) {
|
|
6776
|
+
if (!best || entry.count > best.count) best = entry;
|
|
6777
|
+
}
|
|
6778
|
+
if (!best) return {};
|
|
6779
|
+
return { ...best.icon ? { icon: best.icon } : {}, ...best.iconColor ? { iconColor: best.iconColor } : {} };
|
|
6780
|
+
}
|
|
6685
6781
|
function addPricingCardFeature(tree, index, text) {
|
|
6686
6782
|
return withPricingCollection(tree, (collection) => {
|
|
6687
6783
|
const children = collection.children;
|
|
@@ -6690,7 +6786,7 @@ function addPricingCardFeature(tree, index, text) {
|
|
|
6690
6786
|
const features = pricingFeatureList(target);
|
|
6691
6787
|
if (features.length >= PRICING_FEATURES_MAX) return false;
|
|
6692
6788
|
target.slots = target.slots ?? {};
|
|
6693
|
-
target.slots.features = [...features, { text }];
|
|
6789
|
+
target.slots.features = [...features, { text, ...prevailingFeatureIcon(features) }];
|
|
6694
6790
|
return true;
|
|
6695
6791
|
});
|
|
6696
6792
|
}
|
|
@@ -7302,6 +7398,23 @@ function applyCustomCodeToHead(content) {
|
|
|
7302
7398
|
if (beforeNodes.length > 0) document.head.append(...beforeNodes);
|
|
7303
7399
|
}
|
|
7304
7400
|
|
|
7401
|
+
// src/lib/node-font-size.ts
|
|
7402
|
+
var TEXT_NODE_TYPES = /* @__PURE__ */ new Set(["text", "text/rich", "plain", "link"]);
|
|
7403
|
+
function escapeKey(key) {
|
|
7404
|
+
return typeof CSS !== "undefined" && typeof CSS.escape === "function" ? CSS.escape(key) : key.replace(/["\\]/g, "\\$&");
|
|
7405
|
+
}
|
|
7406
|
+
function measureNodeFontSize(key, type, root) {
|
|
7407
|
+
if (!TEXT_NODE_TYPES.has(type)) return void 0;
|
|
7408
|
+
const el = root.querySelector(`[data-ohw-editable][data-ohw-key="${escapeKey(key)}"]`);
|
|
7409
|
+
if (!el) return void 0;
|
|
7410
|
+
const size = Number.parseFloat(window.getComputedStyle(el).fontSize);
|
|
7411
|
+
return Number.isFinite(size) && size > 0 ? Math.round(size) : void 0;
|
|
7412
|
+
}
|
|
7413
|
+
function withNodeFontSize(node, root) {
|
|
7414
|
+
const fontSize = measureNodeFontSize(node.key, node.type, root);
|
|
7415
|
+
return fontSize === void 0 ? node : { ...node, fontSize };
|
|
7416
|
+
}
|
|
7417
|
+
|
|
7305
7418
|
// src/lib/selectNavContainer.ts
|
|
7306
7419
|
function isOnScreen(el) {
|
|
7307
7420
|
const rect = el.getBoundingClientRect();
|
|
@@ -7890,7 +8003,7 @@ var AI_MOBILE_CSS = [
|
|
|
7890
8003
|
// page's first section. Top only (bottom needs no nav clearance); ~96px approximates the
|
|
7891
8004
|
// template nav's own height (measured ~94px) — there's no shared `--ohw-header-h` var to read
|
|
7892
8005
|
// an exact figure from (no live measurement exists), so this is a safe approximation, not a
|
|
7893
|
-
// pixel-exact fit. Horizontal spacing already comes from `data-ai-
|
|
8006
|
+
// pixel-exact fit. Horizontal spacing already comes from `data-ai-section-inner`.
|
|
7894
8007
|
'[data-ai-overlay-clearance] [data-ai-overlap-layer="overlay"]{padding-top:96px}',
|
|
7895
8008
|
// A full-bleed carousel's height is pure arithmetic: it spans the whole window, so 16/9 turns
|
|
7896
8009
|
// window width straight into height. Measured at 16/9 it came out ~90% of the viewport at EVERY
|
|
@@ -7906,8 +8019,10 @@ var AI_MOBILE_CSS = [
|
|
|
7906
8019
|
"[data-ai-section]{overflow-x:hidden}",
|
|
7907
8020
|
// `:not([data-ai-full-bleed])`: this `!important` gutter beat the inline `padding: 0` that a
|
|
7908
8021
|
// full-bleed section's container sets, so a carousel/media hero that is edge-to-edge on desktop
|
|
7909
|
-
// still got a 20px band of section background down both sides on a phone.
|
|
7910
|
-
|
|
8022
|
+
// still got a 20px band of section background down both sides on a phone. The footer's own
|
|
8023
|
+
// container keeps the unguarded rule below — `data-ai-full-bleed` can never appear on it.
|
|
8024
|
+
"[data-ai-section-inner]:not([data-ai-full-bleed]){padding:0 20px !important}",
|
|
8025
|
+
"[data-ai-container]{padding:0 20px !important}",
|
|
7911
8026
|
"[data-ai-row]{display:flex !important;flex-direction:column !important;align-items:stretch !important}",
|
|
7912
8027
|
"[data-ai-cell]{width:100%;min-width:0}",
|
|
7913
8028
|
// The rule above turns every row into a COLUMN flex container on phones, which silently breaks
|
|
@@ -8112,6 +8227,31 @@ function pricingCardEmphasis(featured, ctx, hasBg) {
|
|
|
8112
8227
|
function textAttrs(ctx, path) {
|
|
8113
8228
|
return ctx.keyFor ? { "data-ohw-key": ctx.keyFor(path), "data-ohw-editable": "text" } : {};
|
|
8114
8229
|
}
|
|
8230
|
+
var AI_RESPONSIVE_CSS = [
|
|
8231
|
+
"@media (max-width: 960px) {",
|
|
8232
|
+
" [data-ai-responsive] [data-ai-grid] { grid-template-columns: repeat(2, 1fr) !important; }",
|
|
8233
|
+
' [data-ai-responsive] [data-ai-grid="1"] { grid-template-columns: 1fr !important; }',
|
|
8234
|
+
"}",
|
|
8235
|
+
"@media (max-width: 640px) {",
|
|
8236
|
+
" [data-ai-responsive] [data-ai-grid] { grid-template-columns: 1fr !important; }",
|
|
8237
|
+
" [data-ai-responsive] [data-ai-columns] > * { grid-column: 1 / -1 !important; }",
|
|
8238
|
+
// Group containers flatten to a column on phones; span placements come along for free.
|
|
8239
|
+
// `:not([data-ai-group="overlap"])` for the same reason as the twin pair in AI_MOBILE_CSS — see
|
|
8240
|
+
// the comment there. This sheet's copy is the narrower selector, so without the exemption it
|
|
8241
|
+
// flattens an `overlap` hero below 640px even though the other rule stands down: measured a 390px
|
|
8242
|
+
// viewport with the heading/CTA in flow *under* the image, 219px of section background where the
|
|
8243
|
+
// layered text used to be.
|
|
8244
|
+
' [data-ai-responsive] [data-ai-group]:not([data-ai-group="overlap"]) { display: flex !important; flex-direction: column !important; }',
|
|
8245
|
+
' [data-ai-responsive] [data-ai-group]:not([data-ai-group="overlap"]) > * { grid-column: auto !important; }',
|
|
8246
|
+
// `:not([data-ai-full-bleed])` for the same reason as the twin rule in AI_MOBILE_CSS: this one
|
|
8247
|
+
// is narrower (0,2,0 vs 0,1,0) and also `!important`, so without the guard it wins outright and
|
|
8248
|
+
// a full-bleed hero gets its 20px side band back below 640px only — the one width where the
|
|
8249
|
+
// other rule had already been taught to stand down.
|
|
8250
|
+
" [data-ai-responsive] [data-ai-section-inner]:not([data-ai-full-bleed]) { padding-left: 20px !important; padding-right: 20px !important; }",
|
|
8251
|
+
" [data-ai-responsive] { overflow-x: hidden; }",
|
|
8252
|
+
" [data-ai-responsive] img { max-width: 100%; }",
|
|
8253
|
+
"}"
|
|
8254
|
+
].join("\n");
|
|
8115
8255
|
var TRANSPARENT_PX = "data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7";
|
|
8116
8256
|
function MediaBox({
|
|
8117
8257
|
refValue,
|
|
@@ -8166,7 +8306,7 @@ function MediaBox({
|
|
|
8166
8306
|
position: fill ? "absolute" : void 0,
|
|
8167
8307
|
inset: fill ? 0 : void 0,
|
|
8168
8308
|
width: fill ? "100%" : fixedSize ? "auto" : "100%",
|
|
8169
|
-
height: fill ? "100%" : void 0,
|
|
8309
|
+
height: fill ? "100%" : fixedSize ? height : void 0,
|
|
8170
8310
|
aspectRatio: fill ? void 0 : aspectRatio,
|
|
8171
8311
|
minHeight: fill || fixedSize ? void 0 : height ?? (aspectRatio ? void 0 : 180),
|
|
8172
8312
|
borderRadius: radius,
|
|
@@ -9662,7 +9802,7 @@ function CollectionBlock({ node, ctx, path }) {
|
|
|
9662
9802
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
9663
9803
|
"div",
|
|
9664
9804
|
{
|
|
9665
|
-
"data-ai-grid":
|
|
9805
|
+
"data-ai-grid": String(itemsPerRow),
|
|
9666
9806
|
"data-ohw-pricing-collection": isPricing ? "" : void 0,
|
|
9667
9807
|
style: {
|
|
9668
9808
|
display: "grid",
|
|
@@ -9964,7 +10104,7 @@ function renderNode(node, ctx, path, ambientAlign) {
|
|
|
9964
10104
|
},
|
|
9965
10105
|
children: [
|
|
9966
10106
|
i > 0 && ctx.heroOverlapFullBleed ? (
|
|
9967
|
-
// The section's `data-ai-
|
|
10107
|
+
// The section's `data-ai-section-inner` gave up its max-width/gutter so the base
|
|
9968
10108
|
// layer (this group's i===0 sibling) can span edge-to-edge — reintroduced here,
|
|
9969
10109
|
// scoped to just the overlay text, so a heading/copy/CTA stack doesn't stretch
|
|
9970
10110
|
// the full section width instead of reading at the usual content width.
|
|
@@ -10383,6 +10523,7 @@ function AiTreeRenderer({
|
|
|
10383
10523
|
...fillHeight ? { "data-ai-fill-height": "" } : {},
|
|
10384
10524
|
...needsOverlayClearance ? { "data-ai-overlay-clearance": "" } : {},
|
|
10385
10525
|
...bgAttrs,
|
|
10526
|
+
"data-ai-responsive": "",
|
|
10386
10527
|
style: {
|
|
10387
10528
|
position: "relative",
|
|
10388
10529
|
padding: `${padCss} 0`,
|
|
@@ -10396,12 +10537,13 @@ function AiTreeRenderer({
|
|
|
10396
10537
|
...fillHeight ? { display: "grid" } : {}
|
|
10397
10538
|
},
|
|
10398
10539
|
children: [
|
|
10399
|
-
|
|
10540
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("style", { children: AI_RESPONSIVE_CSS }),
|
|
10400
10541
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("style", { children: AI_MOBILE_CSS }),
|
|
10542
|
+
isOverlay && backgroundUrl && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: { position: "absolute", inset: 0, background: `rgba(255,255,255,${overlayAlpha})` } }),
|
|
10401
10543
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
10402
10544
|
"div",
|
|
10403
10545
|
{
|
|
10404
|
-
"data-ai-
|
|
10546
|
+
"data-ai-section-inner": "",
|
|
10405
10547
|
...fullBleedMedia ? { "data-ai-full-bleed": "" } : {},
|
|
10406
10548
|
style: {
|
|
10407
10549
|
position: "relative",
|
|
@@ -10418,7 +10560,7 @@ function AiTreeRenderer({
|
|
|
10418
10560
|
children: tree.rows.map((row, r2) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
10419
10561
|
"div",
|
|
10420
10562
|
{
|
|
10421
|
-
"data-ai-
|
|
10563
|
+
"data-ai-columns": "",
|
|
10422
10564
|
style: {
|
|
10423
10565
|
display: "grid",
|
|
10424
10566
|
gridTemplateColumns: "repeat(12, 1fr)",
|
|
@@ -11080,9 +11222,10 @@ function applyAiSectionsToDom(state, options) {
|
|
|
11080
11222
|
if (existing && existing.serialized === serialized && existing.container.isConnected) {
|
|
11081
11223
|
continue;
|
|
11082
11224
|
}
|
|
11083
|
-
const isNewMount = !existing || !existing.container.isConnected;
|
|
11084
11225
|
let container = existing?.container;
|
|
11226
|
+
let isNewMount = false;
|
|
11085
11227
|
if (!container || !container.isConnected) {
|
|
11228
|
+
isNewMount = true;
|
|
11086
11229
|
existing?.root.unmount();
|
|
11087
11230
|
container?.remove();
|
|
11088
11231
|
container = document.createElement("div");
|
|
@@ -17241,7 +17384,7 @@ function apiBase() {
|
|
|
17241
17384
|
function bridgeVersion() {
|
|
17242
17385
|
try {
|
|
17243
17386
|
if (true) {
|
|
17244
|
-
return "0.1.
|
|
17387
|
+
return "0.1.160-next.427";
|
|
17245
17388
|
}
|
|
17246
17389
|
} catch {
|
|
17247
17390
|
}
|
|
@@ -17255,7 +17398,7 @@ function stampBridgeVersionOnDocument() {
|
|
|
17255
17398
|
return;
|
|
17256
17399
|
}
|
|
17257
17400
|
try {
|
|
17258
|
-
const v = true ? "0.1.
|
|
17401
|
+
const v = true ? "0.1.160-next.427" : "";
|
|
17259
17402
|
if (v) {
|
|
17260
17403
|
document.documentElement.setAttribute("data-ohw-bridge-version", v);
|
|
17261
17404
|
window.__OHW_BRIDGE_VERSION__ = v;
|
|
@@ -17933,6 +18076,7 @@ function MediaOverlay({
|
|
|
17933
18076
|
(prev) => prev && prev.fullWidth === width && prev.height === height ? prev : { fullWidth: width, height }
|
|
17934
18077
|
);
|
|
17935
18078
|
}, [isVideo]);
|
|
18079
|
+
const replaceLabel = isVideo ? "Replace video" : hover.elementType === "bg-image" ? "Replace background" : "Replace image";
|
|
17936
18080
|
const replaceMode = buttonSize ? replaceButtonMode({ width: rect.width, height: rect.height }, buttonSize) : "none";
|
|
17937
18081
|
const box = {
|
|
17938
18082
|
position: "fixed",
|
|
@@ -18031,11 +18175,10 @@ function MediaOverlay({
|
|
|
18031
18175
|
className: "flex items-center justify-center cursor-pointer",
|
|
18032
18176
|
style: {
|
|
18033
18177
|
...box,
|
|
18034
|
-
//
|
|
18035
|
-
//
|
|
18036
|
-
//
|
|
18037
|
-
|
|
18038
|
-
pointerEvents: hover.hasTextOverlap || cueOnly ? "none" : "auto",
|
|
18178
|
+
// Visual only. `pointer-events: auto` on this full-bleed rect covered the navbar
|
|
18179
|
+
// (hero bg includes the absolute TopNav) and swallowed CTA press-drag. Text overlay
|
|
18180
|
+
// and cueOnly also need clicks to fall through — Replace / video controls opt back in.
|
|
18181
|
+
pointerEvents: "none",
|
|
18039
18182
|
// Selected: a firm component ring with no wash, so the image reads as chosen rather
|
|
18040
18183
|
// than hovered. Hover keeps the existing tinted preview.
|
|
18041
18184
|
boxShadow: selected ? "inset 0 0 0 2px var(--color-bridge-primary)" : "inset 0 0 0 1.5px var(--color-bridge-primary)",
|
|
@@ -18062,17 +18205,17 @@ function MediaOverlay({
|
|
|
18062
18205
|
},
|
|
18063
18206
|
children: [
|
|
18064
18207
|
isVideo ? /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(import_lucide_react5.Film, { size: 14 }) : /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(import_lucide_react5.ImageIcon, { size: 14 }),
|
|
18065
|
-
|
|
18208
|
+
replaceLabel
|
|
18066
18209
|
]
|
|
18067
18210
|
}
|
|
18068
18211
|
),
|
|
18069
|
-
replaceMode
|
|
18212
|
+
showChrome && replaceMode !== "none" && /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(
|
|
18070
18213
|
Button,
|
|
18071
18214
|
{
|
|
18072
18215
|
"data-ohw-media-overlay": "",
|
|
18073
18216
|
variant: "outline",
|
|
18074
18217
|
size: "sm",
|
|
18075
|
-
"aria-label":
|
|
18218
|
+
"aria-label": replaceLabel,
|
|
18076
18219
|
className: "gap-1.5 cursor-pointer hover:bg-background",
|
|
18077
18220
|
style: {
|
|
18078
18221
|
...OVERLAY_BUTTON_STYLE,
|
|
@@ -18095,7 +18238,7 @@ function MediaOverlay({
|
|
|
18095
18238
|
},
|
|
18096
18239
|
children: [
|
|
18097
18240
|
isVideo ? /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(import_lucide_react5.Film, { size: 14 }) : /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(import_lucide_react5.ImageIcon, { size: 14 }),
|
|
18098
|
-
replaceMode === "full" ?
|
|
18241
|
+
replaceMode === "full" ? replaceLabel : null
|
|
18099
18242
|
]
|
|
18100
18243
|
}
|
|
18101
18244
|
)
|
|
@@ -18164,6 +18307,89 @@ function CarouselOverlay({
|
|
|
18164
18307
|
// src/ui/ai-section/AiSectionOverlay.tsx
|
|
18165
18308
|
var import_react9 = require("react");
|
|
18166
18309
|
var import_lucide_react7 = require("lucide-react");
|
|
18310
|
+
|
|
18311
|
+
// src/lib/ai-change-highlight.ts
|
|
18312
|
+
var STYLE_ID = "ohw-ai-changed-style";
|
|
18313
|
+
var MARK_ATTR = "data-ohw-ai-changed";
|
|
18314
|
+
var HIGHLIGHT_MS = 2200;
|
|
18315
|
+
var HIGHLIGHT_CSS = `
|
|
18316
|
+
@keyframes ohw-ai-changed-pulse {
|
|
18317
|
+
0% { outline-color: rgba(0, 120, 229, 0.95); box-shadow: 0 0 0 5px rgba(0, 120, 229, 0.20); }
|
|
18318
|
+
72% { outline-color: rgba(0, 120, 229, 0.95); box-shadow: 0 0 0 5px rgba(0, 120, 229, 0.12); }
|
|
18319
|
+
100% { outline-color: rgba(0, 120, 229, 0); box-shadow: 0 0 0 5px rgba(0, 120, 229, 0); }
|
|
18320
|
+
}
|
|
18321
|
+
[${MARK_ATTR}] {
|
|
18322
|
+
outline: 2px solid rgba(0, 120, 229, 0.95) !important;
|
|
18323
|
+
outline-offset: 3px !important;
|
|
18324
|
+
animation: ohw-ai-changed-pulse ${HIGHLIGHT_MS}ms ease-out forwards !important;
|
|
18325
|
+
}
|
|
18326
|
+
@media (prefers-reduced-motion: reduce) {
|
|
18327
|
+
[${MARK_ATTR}] { animation: none !important; }
|
|
18328
|
+
}
|
|
18329
|
+
`;
|
|
18330
|
+
function ensureStyleSheet2() {
|
|
18331
|
+
if (document.getElementById(STYLE_ID)) return;
|
|
18332
|
+
const el = document.createElement("style");
|
|
18333
|
+
el.id = STYLE_ID;
|
|
18334
|
+
el.textContent = HIGHLIGHT_CSS;
|
|
18335
|
+
document.head.appendChild(el);
|
|
18336
|
+
}
|
|
18337
|
+
function targetsFor(keys, item) {
|
|
18338
|
+
const out = /* @__PURE__ */ new Set();
|
|
18339
|
+
for (const key of keys) {
|
|
18340
|
+
if (!key) continue;
|
|
18341
|
+
for (const el of Array.from(
|
|
18342
|
+
document.querySelectorAll(`[data-ohw-key="${CSS.escape(key)}"]`)
|
|
18343
|
+
)) {
|
|
18344
|
+
out.add(el);
|
|
18345
|
+
}
|
|
18346
|
+
}
|
|
18347
|
+
if (item) {
|
|
18348
|
+
const section = document.querySelector(`[data-ohw-instance="${CSS.escape(item.sectionId)}"]`) ?? document.querySelector(`[data-ohw-section="${CSS.escape(item.sectionId)}"]`);
|
|
18349
|
+
const stamp = `${item.group}:${item.index}`;
|
|
18350
|
+
const el = section?.querySelector(`[data-ohw-item="${CSS.escape(stamp)}"]`);
|
|
18351
|
+
if (el) out.add(el);
|
|
18352
|
+
}
|
|
18353
|
+
return [...out];
|
|
18354
|
+
}
|
|
18355
|
+
var clearTimer = null;
|
|
18356
|
+
function clearChangeHighlight() {
|
|
18357
|
+
if (clearTimer !== null) {
|
|
18358
|
+
clearTimeout(clearTimer);
|
|
18359
|
+
clearTimer = null;
|
|
18360
|
+
}
|
|
18361
|
+
for (const el of Array.from(document.querySelectorAll(`[${MARK_ATTR}]`))) {
|
|
18362
|
+
el.removeAttribute(MARK_ATTR);
|
|
18363
|
+
}
|
|
18364
|
+
}
|
|
18365
|
+
function highlightChangedElements(keys, item) {
|
|
18366
|
+
clearChangeHighlight();
|
|
18367
|
+
const targets = targetsFor(keys, item);
|
|
18368
|
+
if (targets.length === 0) return 0;
|
|
18369
|
+
ensureStyleSheet2();
|
|
18370
|
+
for (const el of targets) el.setAttribute(MARK_ATTR, "");
|
|
18371
|
+
const rect = targets[0].getBoundingClientRect();
|
|
18372
|
+
if (rect.bottom < 0 || rect.top > window.innerHeight) {
|
|
18373
|
+
targets[0].scrollIntoView({ behavior: "smooth", block: "center" });
|
|
18374
|
+
}
|
|
18375
|
+
clearTimer = setTimeout(clearChangeHighlight, HIGHLIGHT_MS);
|
|
18376
|
+
return targets.length;
|
|
18377
|
+
}
|
|
18378
|
+
function installAiChangeHighlight() {
|
|
18379
|
+
const onMessage = (e) => {
|
|
18380
|
+
const data = e.data;
|
|
18381
|
+
if (data?.type !== "ow:ai-highlight") return;
|
|
18382
|
+
const keys = Array.isArray(data.keys) ? data.keys.filter((k) => typeof k === "string") : [];
|
|
18383
|
+
const raw = data.item;
|
|
18384
|
+
const item = raw && typeof raw.sectionId === "string" && typeof raw.group === "string" && typeof raw.index === "number" ? { sectionId: raw.sectionId, group: raw.group, index: raw.index } : void 0;
|
|
18385
|
+
const found = highlightChangedElements(keys, item);
|
|
18386
|
+
window.parent?.postMessage({ type: "ow:ai-highlight-done", found }, "*");
|
|
18387
|
+
};
|
|
18388
|
+
window.addEventListener("message", onMessage);
|
|
18389
|
+
return () => window.removeEventListener("message", onMessage);
|
|
18390
|
+
}
|
|
18391
|
+
|
|
18392
|
+
// src/ui/ai-section/AiSectionOverlay.tsx
|
|
18167
18393
|
var import_jsx_runtime19 = require("react/jsx-runtime");
|
|
18168
18394
|
var findSectionElement = findByInstanceId;
|
|
18169
18395
|
function readRect(instanceId) {
|
|
@@ -18415,6 +18641,7 @@ function AiSectionOverlay({
|
|
|
18415
18641
|
window.addEventListener("message", onMessage);
|
|
18416
18642
|
return () => window.removeEventListener("message", onMessage);
|
|
18417
18643
|
}, [postToParent2]);
|
|
18644
|
+
(0, import_react9.useEffect)(() => installAiChangeHighlight(), []);
|
|
18418
18645
|
const [hoveredId, setHoveredId] = (0, import_react9.useState)(null);
|
|
18419
18646
|
(0, import_react9.useEffect)(() => {
|
|
18420
18647
|
const onMove = (e) => {
|
|
@@ -18605,7 +18832,7 @@ function AiSectionOverlay({
|
|
|
18605
18832
|
|
|
18606
18833
|
// src/ui/ai-section/AiMediaStripOverlay.tsx
|
|
18607
18834
|
var import_react10 = require("react");
|
|
18608
|
-
var
|
|
18835
|
+
var import_lucide_react9 = require("lucide-react");
|
|
18609
18836
|
|
|
18610
18837
|
// src/lib/ai-media-strip-tree.ts
|
|
18611
18838
|
var MEDIA_STRIP_ITEM_MIN = 1;
|
|
@@ -18719,14 +18946,6 @@ function setMediaStripItemAsset(tree, index, assetId) {
|
|
|
18719
18946
|
return true;
|
|
18720
18947
|
});
|
|
18721
18948
|
}
|
|
18722
|
-
function setMediaStripItemAlt(tree, index, alt) {
|
|
18723
|
-
return withMediaStrip(tree, (block) => {
|
|
18724
|
-
const items = block.items;
|
|
18725
|
-
if (index < 0 || index >= items.length) return false;
|
|
18726
|
-
items[index] = { ...items[index], alt };
|
|
18727
|
-
return true;
|
|
18728
|
-
});
|
|
18729
|
-
}
|
|
18730
18949
|
function setMediaStripItemLink(tree, index, link) {
|
|
18731
18950
|
return withMediaStrip(tree, (block) => {
|
|
18732
18951
|
const items = block.items;
|
|
@@ -18744,11 +18963,117 @@ function setMediaStripItemLink(tree, index, link) {
|
|
|
18744
18963
|
});
|
|
18745
18964
|
}
|
|
18746
18965
|
|
|
18747
|
-
// src/ui/
|
|
18966
|
+
// src/ui/dialog.tsx
|
|
18967
|
+
var React9 = __toESM(require("react"), 1);
|
|
18968
|
+
var import_radix_ui6 = require("radix-ui");
|
|
18969
|
+
var import_lucide_react8 = require("lucide-react");
|
|
18748
18970
|
var import_jsx_runtime20 = require("react/jsx-runtime");
|
|
18749
|
-
|
|
18750
|
-
|
|
18751
|
-
|
|
18971
|
+
function Dialog2({
|
|
18972
|
+
...props
|
|
18973
|
+
}) {
|
|
18974
|
+
return /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_radix_ui6.Dialog.Root, { "data-slot": "dialog", ...props });
|
|
18975
|
+
}
|
|
18976
|
+
function DialogPortal({
|
|
18977
|
+
...props
|
|
18978
|
+
}) {
|
|
18979
|
+
return /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_radix_ui6.Dialog.Portal, { ...props });
|
|
18980
|
+
}
|
|
18981
|
+
function DialogOverlay({
|
|
18982
|
+
className,
|
|
18983
|
+
...props
|
|
18984
|
+
}) {
|
|
18985
|
+
return /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
|
|
18986
|
+
import_radix_ui6.Dialog.Overlay,
|
|
18987
|
+
{
|
|
18988
|
+
"data-slot": "dialog-overlay",
|
|
18989
|
+
"data-ohw-link-modal-root": "",
|
|
18990
|
+
className: cn("fixed inset-0 z-[2147483646] bg-black/50", className),
|
|
18991
|
+
...props
|
|
18992
|
+
}
|
|
18993
|
+
);
|
|
18994
|
+
}
|
|
18995
|
+
var DialogContent = React9.forwardRef(
|
|
18996
|
+
({ className, children, showCloseButton = true, container, ...props }, ref) => {
|
|
18997
|
+
const positionMode = container ? "absolute" : "fixed";
|
|
18998
|
+
return /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)(DialogPortal, { container: container ?? void 0, children: [
|
|
18999
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)(DialogOverlay, { className: cn(positionMode, "inset-0") }),
|
|
19000
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsxs)(
|
|
19001
|
+
import_radix_ui6.Dialog.Content,
|
|
19002
|
+
{
|
|
19003
|
+
ref,
|
|
19004
|
+
"data-slot": "dialog-content",
|
|
19005
|
+
className: cn(
|
|
19006
|
+
positionMode,
|
|
19007
|
+
"left-1/2 top-1/2 z-[2147483647] flex w-full max-w-[448px] -translate-x-1/2 -translate-y-1/2 flex-col overflow-visible",
|
|
19008
|
+
"rounded-xl border border-border bg-background font-sans shadow-lg outline-none",
|
|
19009
|
+
container ? "max-h-[calc(100%-32px)]" : "max-h-[calc(100vh-32px)]",
|
|
19010
|
+
className
|
|
19011
|
+
),
|
|
19012
|
+
onMouseDown: (e) => e.stopPropagation(),
|
|
19013
|
+
...props,
|
|
19014
|
+
children: [
|
|
19015
|
+
children,
|
|
19016
|
+
showCloseButton ? /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
|
|
19017
|
+
import_radix_ui6.Dialog.Close,
|
|
19018
|
+
{
|
|
19019
|
+
type: "button",
|
|
19020
|
+
className: "absolute right-[9px] top-[9px] rounded-sm p-1.5 text-foreground hover:bg-muted/50",
|
|
19021
|
+
"aria-label": "Close",
|
|
19022
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_lucide_react8.X, { size: 16, "aria-hidden": true })
|
|
19023
|
+
}
|
|
19024
|
+
) : null
|
|
19025
|
+
]
|
|
19026
|
+
}
|
|
19027
|
+
)
|
|
19028
|
+
] });
|
|
19029
|
+
}
|
|
19030
|
+
);
|
|
19031
|
+
DialogContent.displayName = import_radix_ui6.Dialog.Content.displayName;
|
|
19032
|
+
function DialogHeader({
|
|
19033
|
+
className,
|
|
19034
|
+
...props
|
|
19035
|
+
}) {
|
|
19036
|
+
return /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("div", { className: cn("flex flex-col gap-1.5", className), ...props });
|
|
19037
|
+
}
|
|
19038
|
+
function DialogFooter({
|
|
19039
|
+
className,
|
|
19040
|
+
...props
|
|
19041
|
+
}) {
|
|
19042
|
+
return /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
|
|
19043
|
+
"div",
|
|
19044
|
+
{
|
|
19045
|
+
className: cn("flex items-center justify-end gap-2", className),
|
|
19046
|
+
...props
|
|
19047
|
+
}
|
|
19048
|
+
);
|
|
19049
|
+
}
|
|
19050
|
+
var DialogTitle = React9.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
|
|
19051
|
+
import_radix_ui6.Dialog.Title,
|
|
19052
|
+
{
|
|
19053
|
+
ref,
|
|
19054
|
+
className: cn(
|
|
19055
|
+
"text-lg font-semibold leading-none tracking-tight text-card-foreground",
|
|
19056
|
+
className
|
|
19057
|
+
),
|
|
19058
|
+
...props
|
|
19059
|
+
}
|
|
19060
|
+
));
|
|
19061
|
+
DialogTitle.displayName = import_radix_ui6.Dialog.Title.displayName;
|
|
19062
|
+
var DialogDescription = React9.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
|
|
19063
|
+
import_radix_ui6.Dialog.Description,
|
|
19064
|
+
{
|
|
19065
|
+
ref,
|
|
19066
|
+
className: cn("text-sm text-muted-foreground", className),
|
|
19067
|
+
...props
|
|
19068
|
+
}
|
|
19069
|
+
));
|
|
19070
|
+
DialogDescription.displayName = import_radix_ui6.Dialog.Description.displayName;
|
|
19071
|
+
var DialogClose = import_radix_ui6.Dialog.Close;
|
|
19072
|
+
|
|
19073
|
+
// src/ui/ai-section/AiMediaStripOverlay.tsx
|
|
19074
|
+
var import_jsx_runtime21 = require("react/jsx-runtime");
|
|
19075
|
+
var PRIMARY3 = "var(--ohw-primary, #0885FE)";
|
|
19076
|
+
var CHROME_SELECTOR = "[data-ohw-toolbar], [data-ohw-edit-chrome], [data-ohw-item-interaction], [data-ohw-link-modal-root], [data-ohw-section-picker], [data-ohw-ai-review], [data-ohw-more-menu]";
|
|
18752
19077
|
function findMediaStripItemElement(sectionId, index) {
|
|
18753
19078
|
const sectionEl = findByInstanceId(sectionId);
|
|
18754
19079
|
if (!sectionEl) return null;
|
|
@@ -18758,14 +19083,35 @@ function findMediaStripItemElement(sectionId, index) {
|
|
|
18758
19083
|
}
|
|
18759
19084
|
return null;
|
|
18760
19085
|
}
|
|
18761
|
-
function
|
|
18762
|
-
|
|
19086
|
+
function itemRefFromTarget(target) {
|
|
19087
|
+
if (!(target instanceof Element)) return null;
|
|
19088
|
+
if (target.closest(CHROME_SELECTOR)) return null;
|
|
19089
|
+
const itemEl = target.closest("[data-ohw-media-strip-item]");
|
|
19090
|
+
if (!itemEl) return null;
|
|
19091
|
+
const sectionEl = itemEl.closest("[data-ohw-section]");
|
|
19092
|
+
const unit = sectionEl ? movableUnit(sectionEl) : null;
|
|
19093
|
+
const sectionId = unit ? instanceIdOf(unit) || null : null;
|
|
19094
|
+
const index = Number(itemEl.dataset.ohwMediaStripIndex);
|
|
19095
|
+
if (!sectionId || Number.isNaN(index)) return null;
|
|
19096
|
+
return { sectionId, index };
|
|
19097
|
+
}
|
|
19098
|
+
function sameRef(a, b) {
|
|
19099
|
+
return a?.sectionId === b?.sectionId && a?.index === b?.index;
|
|
19100
|
+
}
|
|
19101
|
+
function rectOf(el) {
|
|
18763
19102
|
if (!el) return null;
|
|
18764
19103
|
const r2 = el.getBoundingClientRect();
|
|
18765
19104
|
if (r2.width <= 0 || r2.height <= 0) return null;
|
|
18766
19105
|
return { top: r2.top, left: r2.left, width: r2.width, height: r2.height };
|
|
18767
19106
|
}
|
|
18768
|
-
function
|
|
19107
|
+
function readRect2(ref) {
|
|
19108
|
+
return rectOf(ref && findMediaStripItemElement(ref.sectionId, ref.index));
|
|
19109
|
+
}
|
|
19110
|
+
function readStripRect(ref) {
|
|
19111
|
+
const item = ref && findMediaStripItemElement(ref.sectionId, ref.index);
|
|
19112
|
+
return rectOf(item?.closest("[data-ohw-media-strip]") ?? item);
|
|
19113
|
+
}
|
|
19114
|
+
function useLiveItemRect(ref, strip = false) {
|
|
18769
19115
|
const [rect, setRect] = (0, import_react10.useState)(null);
|
|
18770
19116
|
(0, import_react10.useEffect)(() => {
|
|
18771
19117
|
if (!ref) {
|
|
@@ -18773,7 +19119,7 @@ function useLiveItemRect(ref) {
|
|
|
18773
19119
|
return;
|
|
18774
19120
|
}
|
|
18775
19121
|
const update = () => {
|
|
18776
|
-
const next = readRect2(ref);
|
|
19122
|
+
const next = strip ? readStripRect(ref) : readRect2(ref);
|
|
18777
19123
|
setRect(
|
|
18778
19124
|
(prev) => prev && next && prev.top === next.top && prev.left === next.left && prev.width === next.width && prev.height === next.height ? prev : next
|
|
18779
19125
|
);
|
|
@@ -18788,9 +19134,49 @@ function useLiveItemRect(ref) {
|
|
|
18788
19134
|
window.removeEventListener("resize", update);
|
|
18789
19135
|
clearInterval(interval);
|
|
18790
19136
|
};
|
|
18791
|
-
}, [ref?.sectionId, ref?.index]);
|
|
19137
|
+
}, [ref?.sectionId, ref?.index, strip]);
|
|
18792
19138
|
return rect;
|
|
18793
19139
|
}
|
|
19140
|
+
var TOOLBAR_STRIP_GAP = 52;
|
|
19141
|
+
var TOOLBAR_STRIP_GAP_MOBILE = 42;
|
|
19142
|
+
var TOOLBAR_EDGE_MARGIN2 = 4;
|
|
19143
|
+
function StripToolbarSlot({ stripRect, children }) {
|
|
19144
|
+
const slotRef = (0, import_react10.useRef)(null);
|
|
19145
|
+
const [shift, setShift] = (0, import_react10.useState)(0);
|
|
19146
|
+
const centerX = stripRect.left + stripRect.width / 2;
|
|
19147
|
+
(0, import_react10.useLayoutEffect)(() => {
|
|
19148
|
+
const slot = slotRef.current;
|
|
19149
|
+
if (!slot) return;
|
|
19150
|
+
const clamp = () => {
|
|
19151
|
+
const w = slot.offsetWidth;
|
|
19152
|
+
if (w <= 0) return;
|
|
19153
|
+
const half = w / 2;
|
|
19154
|
+
const clamped = Math.max(TOOLBAR_EDGE_MARGIN2 + half, Math.min(centerX, window.innerWidth - TOOLBAR_EDGE_MARGIN2 - half));
|
|
19155
|
+
setShift((prev) => Math.abs(prev - (clamped - centerX)) < 0.5 ? prev : clamped - centerX);
|
|
19156
|
+
};
|
|
19157
|
+
clamp();
|
|
19158
|
+
const ro = new ResizeObserver(clamp);
|
|
19159
|
+
ro.observe(slot);
|
|
19160
|
+
return () => ro.disconnect();
|
|
19161
|
+
}, [centerX, children]);
|
|
19162
|
+
const mobile = window.innerWidth <= 480;
|
|
19163
|
+
return /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
19164
|
+
"div",
|
|
19165
|
+
{
|
|
19166
|
+
ref: slotRef,
|
|
19167
|
+
"data-ohw-bridge": "",
|
|
19168
|
+
"data-ohw-item-interaction": "",
|
|
19169
|
+
className: "pointer-events-auto fixed",
|
|
19170
|
+
style: {
|
|
19171
|
+
top: stripRect.top - (mobile ? TOOLBAR_STRIP_GAP_MOBILE : TOOLBAR_STRIP_GAP),
|
|
19172
|
+
left: centerX + shift,
|
|
19173
|
+
transform: "translate(-50%, -100%)",
|
|
19174
|
+
zIndex: 2147483645
|
|
19175
|
+
},
|
|
19176
|
+
children
|
|
19177
|
+
}
|
|
19178
|
+
);
|
|
19179
|
+
}
|
|
18794
19180
|
function requestValidateTree(postToParent2, tree) {
|
|
18795
19181
|
return new Promise((resolve) => {
|
|
18796
19182
|
const id = `ai-validate-${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 8)}`;
|
|
@@ -18827,116 +19213,72 @@ function requestAssetPick(postToParent2) {
|
|
|
18827
19213
|
postToParent2({ type: "ow:asset-pick", id });
|
|
18828
19214
|
});
|
|
18829
19215
|
}
|
|
18830
|
-
function
|
|
19216
|
+
function ToolbarAction({
|
|
18831
19217
|
label,
|
|
18832
19218
|
onClick,
|
|
18833
|
-
disabled,
|
|
18834
|
-
active
|
|
19219
|
+
disabled = false,
|
|
19220
|
+
active = false,
|
|
19221
|
+
children
|
|
18835
19222
|
}) {
|
|
18836
|
-
|
|
18837
|
-
|
|
18838
|
-
{
|
|
18839
|
-
|
|
18840
|
-
|
|
18841
|
-
disabled,
|
|
18842
|
-
style: {
|
|
18843
|
-
height: 28,
|
|
18844
|
-
padding: "0 10px",
|
|
18845
|
-
display: "inline-flex",
|
|
18846
|
-
alignItems: "center",
|
|
18847
|
-
gap: 4,
|
|
18848
|
-
borderRadius: 999,
|
|
18849
|
-
border: "none",
|
|
18850
|
-
cursor: disabled ? "default" : "pointer",
|
|
18851
|
-
background: active ? OHW_BLUE_DARK : "#ffffff",
|
|
18852
|
-
color: active ? "#ffffff" : OHW_BLUE_DARK,
|
|
18853
|
-
opacity: disabled ? 0.4 : 1,
|
|
18854
|
-
fontSize: 12,
|
|
18855
|
-
lineHeight: "16px",
|
|
18856
|
-
fontFamily: "Figtree, ui-sans-serif, system-ui, sans-serif",
|
|
18857
|
-
whiteSpace: "nowrap",
|
|
18858
|
-
flex: "0 0 auto"
|
|
18859
|
-
},
|
|
18860
|
-
children: label
|
|
18861
|
-
}
|
|
18862
|
-
);
|
|
19223
|
+
const button = /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(CustomToolbarButton, { type: "button", "aria-label": label, disabled, active, onClick, className: "size-8", children });
|
|
19224
|
+
return /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(Tooltip, { children: [
|
|
19225
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(TooltipTrigger, { asChild: true, children: disabled ? /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("span", { className: "inline-flex", children: button }) : button }),
|
|
19226
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(TooltipContent, { side: "bottom", sideOffset: 8, children: label })
|
|
19227
|
+
] });
|
|
18863
19228
|
}
|
|
18864
|
-
function
|
|
18865
|
-
|
|
18866
|
-
|
|
18867
|
-
|
|
18868
|
-
|
|
18869
|
-
|
|
18870
|
-
|
|
18871
|
-
|
|
18872
|
-
|
|
18873
|
-
|
|
18874
|
-
|
|
18875
|
-
|
|
18876
|
-
|
|
18877
|
-
|
|
18878
|
-
|
|
18879
|
-
|
|
18880
|
-
|
|
18881
|
-
|
|
18882
|
-
|
|
18883
|
-
|
|
18884
|
-
|
|
18885
|
-
|
|
18886
|
-
|
|
18887
|
-
|
|
18888
|
-
|
|
18889
|
-
|
|
18890
|
-
|
|
18891
|
-
|
|
18892
|
-
|
|
18893
|
-
|
|
18894
|
-
|
|
18895
|
-
|
|
18896
|
-
|
|
18897
|
-
|
|
18898
|
-
|
|
18899
|
-
|
|
18900
|
-
|
|
18901
|
-
|
|
18902
|
-
|
|
18903
|
-
|
|
18904
|
-
|
|
18905
|
-
|
|
18906
|
-
|
|
18907
|
-
|
|
18908
|
-
if (e.key === "Escape") {
|
|
18909
|
-
setDraft(value);
|
|
18910
|
-
e.currentTarget.blur();
|
|
18911
|
-
}
|
|
18912
|
-
},
|
|
18913
|
-
placeholder: "Describe this image",
|
|
18914
|
-
"aria-label": "Image alt text",
|
|
18915
|
-
style: {
|
|
18916
|
-
flex: 1,
|
|
18917
|
-
minWidth: 0,
|
|
18918
|
-
border: "none",
|
|
18919
|
-
outline: "none",
|
|
18920
|
-
background: "transparent",
|
|
18921
|
-
fontSize: 12,
|
|
18922
|
-
lineHeight: "16px",
|
|
18923
|
-
fontFamily: "Figtree, ui-sans-serif, system-ui, sans-serif",
|
|
18924
|
-
color: "#1f2937"
|
|
18925
|
-
}
|
|
18926
|
-
}
|
|
18927
|
-
)
|
|
18928
|
-
]
|
|
18929
|
-
}
|
|
18930
|
-
);
|
|
19229
|
+
function ToolbarSeparator() {
|
|
19230
|
+
return /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("span", { "aria-hidden": true, className: "mx-0.5 block h-6 w-px shrink-0 bg-border" });
|
|
19231
|
+
}
|
|
19232
|
+
function OptionMenu({
|
|
19233
|
+
label,
|
|
19234
|
+
value,
|
|
19235
|
+
options,
|
|
19236
|
+
onChange
|
|
19237
|
+
}) {
|
|
19238
|
+
const current = options.find((o) => o.value === value) ?? options[0];
|
|
19239
|
+
return /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: "flex items-center gap-1.5 pl-1.5", children: [
|
|
19240
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("span", { className: "text-xs text-muted-foreground", children: label }),
|
|
19241
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(DropdownMenu, { modal: false, children: [
|
|
19242
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(DropdownMenuTrigger, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(
|
|
19243
|
+
"button",
|
|
19244
|
+
{
|
|
19245
|
+
type: "button",
|
|
19246
|
+
"aria-label": label,
|
|
19247
|
+
className: "inline-flex h-8 min-w-[76px] items-center gap-[7px] rounded-[6px] bg-transparent px-2 text-[13px] font-medium text-foreground transition-colors hover:bg-muted data-[state=open]:bg-muted",
|
|
19248
|
+
children: [
|
|
19249
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("span", { className: "flex-1 text-left", children: current.label }),
|
|
19250
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_lucide_react9.ChevronDown, { size: 16, style: { pointerEvents: "none" } })
|
|
19251
|
+
]
|
|
19252
|
+
}
|
|
19253
|
+
) }),
|
|
19254
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(DropdownMenuContent, { align: "end", sideOffset: 8, className: "w-[132px] min-w-[132px] p-1", children: options.map((option) => {
|
|
19255
|
+
const selected = option.value === value;
|
|
19256
|
+
return /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(
|
|
19257
|
+
DropdownMenuItem,
|
|
19258
|
+
{
|
|
19259
|
+
role: "menuitemradio",
|
|
19260
|
+
"aria-checked": selected,
|
|
19261
|
+
onSelect: () => onChange(option.value),
|
|
19262
|
+
className: cn("grid grid-cols-[1fr_16px] gap-2 py-2 pl-2 pr-2 text-[13px]", selected && "bg-muted"),
|
|
19263
|
+
children: [
|
|
19264
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("span", { children: option.label }),
|
|
19265
|
+
selected && /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_lucide_react9.Check, { size: 16, className: "text-bridge-primary" })
|
|
19266
|
+
]
|
|
19267
|
+
},
|
|
19268
|
+
option.value
|
|
19269
|
+
);
|
|
19270
|
+
}) })
|
|
19271
|
+
] })
|
|
19272
|
+
] });
|
|
18931
19273
|
}
|
|
18932
19274
|
var VARIANTS = [
|
|
18933
19275
|
{ value: "logos", label: "Logos" },
|
|
18934
19276
|
{ value: "reel", label: "Reel" }
|
|
18935
19277
|
];
|
|
18936
19278
|
var ALIGNS = [
|
|
18937
|
-
{ value: "left", label: "
|
|
18938
|
-
{ value: "center", label: "
|
|
18939
|
-
{ value: "right", label: "
|
|
19279
|
+
{ value: "left", label: "Align left", Icon: import_lucide_react9.AlignLeft },
|
|
19280
|
+
{ value: "center", label: "Align center", Icon: import_lucide_react9.AlignCenter },
|
|
19281
|
+
{ value: "right", label: "Align right", Icon: import_lucide_react9.AlignRight }
|
|
18940
19282
|
];
|
|
18941
19283
|
var HOVERS = [
|
|
18942
19284
|
{ value: "none", label: "None" },
|
|
@@ -18944,104 +19286,104 @@ var HOVERS = [
|
|
|
18944
19286
|
{ value: "zoom", label: "Zoom" },
|
|
18945
19287
|
{ value: "fade", label: "Fade" }
|
|
18946
19288
|
];
|
|
18947
|
-
var TREATMENTS = [
|
|
18948
|
-
{ value: "color", label: "Color" },
|
|
18949
|
-
{ value: "grayscale", label: "Grayscale" }
|
|
18950
|
-
];
|
|
18951
19289
|
var HTTP_URL_RE = /^https?:\/\/\S+$/i;
|
|
18952
|
-
function
|
|
18953
|
-
|
|
19290
|
+
function LinkModal({
|
|
19291
|
+
href,
|
|
19292
|
+
linkTarget,
|
|
19293
|
+
onClose,
|
|
19294
|
+
onSave
|
|
19295
|
+
}) {
|
|
19296
|
+
const [draft, setDraft] = (0, import_react10.useState)(href);
|
|
19297
|
+
const [newTab, setNewTab] = (0, import_react10.useState)(linkTarget !== "same-tab");
|
|
18954
19298
|
const [invalid, setInvalid] = (0, import_react10.useState)(false);
|
|
18955
|
-
|
|
18956
|
-
setDraft(value);
|
|
18957
|
-
setInvalid(false);
|
|
18958
|
-
}, [value]);
|
|
18959
|
-
const commit = () => {
|
|
19299
|
+
const save = () => {
|
|
18960
19300
|
const next = draft.trim();
|
|
18961
|
-
if (next
|
|
18962
|
-
|
|
18963
|
-
|
|
18964
|
-
onCommit(next);
|
|
18965
|
-
};
|
|
18966
|
-
return /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)(
|
|
18967
|
-
"div",
|
|
18968
|
-
{
|
|
18969
|
-
style: {
|
|
18970
|
-
display: "flex",
|
|
18971
|
-
alignItems: "center",
|
|
18972
|
-
gap: 6,
|
|
18973
|
-
height: 28,
|
|
18974
|
-
padding: "0 12px",
|
|
18975
|
-
borderRadius: 999,
|
|
18976
|
-
background: "#ffffff",
|
|
18977
|
-
width: "100%",
|
|
18978
|
-
maxWidth: 260,
|
|
18979
|
-
boxSizing: "border-box",
|
|
18980
|
-
boxShadow: invalid ? "inset 0 0 0 1.5px #EF4444" : "none"
|
|
18981
|
-
},
|
|
18982
|
-
children: [
|
|
18983
|
-
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
|
|
18984
|
-
"span",
|
|
18985
|
-
{
|
|
18986
|
-
style: {
|
|
18987
|
-
flex: "0 0 auto",
|
|
18988
|
-
color: OHW_BLUE_DARK,
|
|
18989
|
-
fontSize: 10,
|
|
18990
|
-
fontWeight: 700,
|
|
18991
|
-
textTransform: "uppercase",
|
|
18992
|
-
letterSpacing: 0.4
|
|
18993
|
-
},
|
|
18994
|
-
children: "Link"
|
|
18995
|
-
}
|
|
18996
|
-
),
|
|
18997
|
-
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
|
|
18998
|
-
"input",
|
|
18999
|
-
{
|
|
19000
|
-
type: "text",
|
|
19001
|
-
inputMode: "url",
|
|
19002
|
-
value: draft,
|
|
19003
|
-
onChange: (e) => setDraft(e.target.value),
|
|
19004
|
-
onBlur: commit,
|
|
19005
|
-
onKeyDown: (e) => {
|
|
19006
|
-
if (e.key === "Enter") e.currentTarget.blur();
|
|
19007
|
-
if (e.key === "Escape") {
|
|
19008
|
-
setDraft(value);
|
|
19009
|
-
setInvalid(false);
|
|
19010
|
-
e.currentTarget.blur();
|
|
19011
|
-
}
|
|
19012
|
-
},
|
|
19013
|
-
placeholder: "https://example.com",
|
|
19014
|
-
"aria-label": "Image link URL",
|
|
19015
|
-
"aria-invalid": invalid,
|
|
19016
|
-
style: {
|
|
19017
|
-
flex: 1,
|
|
19018
|
-
minWidth: 0,
|
|
19019
|
-
border: "none",
|
|
19020
|
-
outline: "none",
|
|
19021
|
-
background: "transparent",
|
|
19022
|
-
fontSize: 12,
|
|
19023
|
-
lineHeight: "16px",
|
|
19024
|
-
fontFamily: "Figtree, ui-sans-serif, system-ui, sans-serif",
|
|
19025
|
-
color: "#1f2937"
|
|
19026
|
-
}
|
|
19027
|
-
}
|
|
19028
|
-
)
|
|
19029
|
-
]
|
|
19301
|
+
if (next && !HTTP_URL_RE.test(next)) {
|
|
19302
|
+
setInvalid(true);
|
|
19303
|
+
return;
|
|
19030
19304
|
}
|
|
19031
|
-
|
|
19305
|
+
onSave(next, newTab ? "new-tab" : "same-tab");
|
|
19306
|
+
onClose();
|
|
19307
|
+
};
|
|
19308
|
+
return /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(Dialog2, { open: true, onOpenChange: (open) => !open && onClose(), children: /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(DialogContent, { "data-ohw-link-modal-root": "", className: "max-w-[400px] gap-4 p-5", children: [
|
|
19309
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(DialogHeader, { children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(DialogTitle, { className: "text-base", children: "Image link" }) }),
|
|
19310
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: "flex flex-col gap-3", children: [
|
|
19311
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
19312
|
+
"input",
|
|
19313
|
+
{
|
|
19314
|
+
autoFocus: true,
|
|
19315
|
+
type: "text",
|
|
19316
|
+
inputMode: "url",
|
|
19317
|
+
value: draft,
|
|
19318
|
+
onChange: (e) => {
|
|
19319
|
+
setDraft(e.target.value);
|
|
19320
|
+
setInvalid(false);
|
|
19321
|
+
},
|
|
19322
|
+
onKeyDown: (e) => {
|
|
19323
|
+
if (e.key === "Enter") save();
|
|
19324
|
+
},
|
|
19325
|
+
placeholder: "https://example.com",
|
|
19326
|
+
"aria-label": "Image link URL",
|
|
19327
|
+
"aria-invalid": invalid,
|
|
19328
|
+
className: cn(
|
|
19329
|
+
"h-9 w-full rounded-[6px] border border-border bg-background px-3 text-[13px] text-foreground outline-none placeholder:text-muted-foreground/70 focus:border-bridge-primary",
|
|
19330
|
+
invalid && "border-destructive focus:border-destructive"
|
|
19331
|
+
)
|
|
19332
|
+
}
|
|
19333
|
+
),
|
|
19334
|
+
invalid && /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("p", { className: "text-xs text-destructive", children: "Enter a full URL starting with http:// or https://" }),
|
|
19335
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("label", { className: "flex items-center gap-2 text-[13px] text-foreground", children: [
|
|
19336
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("input", { type: "checkbox", checked: newTab, onChange: (e) => setNewTab(e.target.checked) }),
|
|
19337
|
+
"Open in new tab"
|
|
19338
|
+
] })
|
|
19339
|
+
] }),
|
|
19340
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(DialogFooter, { children: [
|
|
19341
|
+
href && /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
19342
|
+
"button",
|
|
19343
|
+
{
|
|
19344
|
+
type: "button",
|
|
19345
|
+
onClick: () => {
|
|
19346
|
+
onSave("", "new-tab");
|
|
19347
|
+
onClose();
|
|
19348
|
+
},
|
|
19349
|
+
className: "mr-auto rounded-[6px] px-3 py-2 text-[13px] font-medium text-destructive transition-colors hover:bg-muted",
|
|
19350
|
+
children: "Remove link"
|
|
19351
|
+
}
|
|
19352
|
+
),
|
|
19353
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
19354
|
+
"button",
|
|
19355
|
+
{
|
|
19356
|
+
type: "button",
|
|
19357
|
+
onClick: onClose,
|
|
19358
|
+
className: "rounded-[6px] px-3 py-2 text-[13px] font-medium text-foreground transition-colors hover:bg-muted",
|
|
19359
|
+
children: "Cancel"
|
|
19360
|
+
}
|
|
19361
|
+
),
|
|
19362
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
19363
|
+
"button",
|
|
19364
|
+
{
|
|
19365
|
+
type: "button",
|
|
19366
|
+
onClick: save,
|
|
19367
|
+
className: "rounded-[6px] bg-bridge-primary px-3 py-2 text-[13px] font-medium text-primary-foreground transition-opacity hover:opacity-90",
|
|
19368
|
+
children: "Save"
|
|
19369
|
+
}
|
|
19370
|
+
)
|
|
19371
|
+
] })
|
|
19372
|
+
] }) });
|
|
19032
19373
|
}
|
|
19033
19374
|
function MediaStripToolbar({
|
|
19034
19375
|
entry,
|
|
19035
19376
|
index,
|
|
19036
19377
|
pending,
|
|
19037
19378
|
error,
|
|
19379
|
+
itemEditOn,
|
|
19380
|
+
onToggleItemEdit,
|
|
19038
19381
|
onSetVariant,
|
|
19039
19382
|
onSetAlign,
|
|
19040
19383
|
onSetHover,
|
|
19041
19384
|
onSetTreatment,
|
|
19042
19385
|
onResize,
|
|
19043
|
-
|
|
19044
|
-
onSetLink,
|
|
19386
|
+
onOpenLink,
|
|
19045
19387
|
onAddItem,
|
|
19046
19388
|
onRemoveItem,
|
|
19047
19389
|
onChangeImage,
|
|
@@ -19050,81 +19392,102 @@ function MediaStripToolbar({
|
|
|
19050
19392
|
}) {
|
|
19051
19393
|
const items = mediaStripItems(entry.tree);
|
|
19052
19394
|
const itemCount = items.length;
|
|
19053
|
-
const currentAlt = items[index]?.alt ?? "";
|
|
19054
|
-
const currentHref = items[index]?.href ?? "";
|
|
19055
|
-
const currentTarget = items[index]?.linkTarget === "same-tab" ? "same-tab" : "new-tab";
|
|
19056
19395
|
const slots = findMediaStripSlots(entry.tree);
|
|
19057
19396
|
const variant = slots?.variant === "reel" ? "reel" : "logos";
|
|
19058
19397
|
const align = slots?.align === "left" || slots?.align === "right" ? slots.align : "center";
|
|
19059
19398
|
const hover = slots?.hover === "none" || slots?.hover === "lift" || slots?.hover === "zoom" || slots?.hover === "fade" ? slots.hover : "lift";
|
|
19060
19399
|
const treatment = slots?.treatment === "color" || slots?.treatment === "grayscale" ? slots.treatment : variant === "logos" ? "grayscale" : "color";
|
|
19061
19400
|
const sizeValue = variant === "logos" ? typeof slots?.logoMaxHeight === "number" ? slots.logoMaxHeight : 48 : typeof slots?.cardWidth === "number" ? slots.cardWidth : 240;
|
|
19062
|
-
const
|
|
19063
|
-
const
|
|
19064
|
-
|
|
19065
|
-
gap: 6,
|
|
19066
|
-
flexWrap: "nowrap",
|
|
19067
|
-
justifyContent: "center",
|
|
19068
|
-
overflowX: "auto",
|
|
19069
|
-
WebkitOverflowScrolling: "touch",
|
|
19070
|
-
width: "100%",
|
|
19071
|
-
scrollbarWidth: "none"
|
|
19072
|
-
} : { display: "flex", gap: 6, flexWrap: "nowrap", justifyContent: "center" };
|
|
19073
|
-
return /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)(
|
|
19401
|
+
const mobile = window.innerWidth <= 480;
|
|
19402
|
+
const gatedLabel = (label) => itemEditOn ? label : "Turn on the star to edit this image";
|
|
19403
|
+
return /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(TooltipProvider, { delayDuration: 0, children: /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(
|
|
19074
19404
|
"div",
|
|
19075
19405
|
{
|
|
19076
19406
|
"data-ohw-bridge": "",
|
|
19077
19407
|
"data-ohw-toolbar": "",
|
|
19078
19408
|
onMouseDown: (e) => e.stopPropagation(),
|
|
19079
|
-
|
|
19080
|
-
|
|
19081
|
-
flexDirection: "column",
|
|
19082
|
-
gap: 6,
|
|
19083
|
-
alignItems: "center",
|
|
19084
|
-
background: OHW_BLUE,
|
|
19085
|
-
padding: 8,
|
|
19086
|
-
borderRadius: 12,
|
|
19087
|
-
boxShadow: "0 8px 24px rgba(0,0,0,0.25)",
|
|
19088
|
-
pointerEvents: pending ? "none" : "auto",
|
|
19089
|
-
opacity: pending ? 0.6 : 1,
|
|
19090
|
-
maxWidth: isMobile ? "calc(100vw - 24px)" : "none"
|
|
19091
|
-
},
|
|
19409
|
+
className: cn("flex flex-col items-center gap-1.5 font-sans", pending && "pointer-events-none opacity-60"),
|
|
19410
|
+
style: { maxWidth: mobile ? "calc(100vw - 24px)" : void 0 },
|
|
19092
19411
|
children: [
|
|
19093
|
-
/* @__PURE__ */ (0,
|
|
19094
|
-
|
|
19095
|
-
|
|
19096
|
-
|
|
19097
|
-
|
|
19098
|
-
|
|
19099
|
-
|
|
19100
|
-
|
|
19101
|
-
|
|
19102
|
-
|
|
19103
|
-
|
|
19104
|
-
|
|
19105
|
-
|
|
19106
|
-
|
|
19107
|
-
|
|
19108
|
-
|
|
19109
|
-
|
|
19110
|
-
|
|
19111
|
-
|
|
19112
|
-
|
|
19113
|
-
|
|
19114
|
-
|
|
19115
|
-
|
|
19116
|
-
|
|
19117
|
-
|
|
19118
|
-
|
|
19119
|
-
|
|
19120
|
-
|
|
19121
|
-
|
|
19122
|
-
|
|
19123
|
-
|
|
19124
|
-
|
|
19412
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(
|
|
19413
|
+
"div",
|
|
19414
|
+
{
|
|
19415
|
+
className: cn(
|
|
19416
|
+
"flex items-center gap-1 rounded-[10px] border border-border bg-background p-1 whitespace-nowrap",
|
|
19417
|
+
"shadow-[0px_10px_15px_-3px_rgba(0,0,0,0.1),0px_4px_6px_-4px_rgba(0,0,0,0.1)]",
|
|
19418
|
+
mobile ? "flex-wrap justify-center" : "flex-nowrap"
|
|
19419
|
+
),
|
|
19420
|
+
children: [
|
|
19421
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(Tooltip, { children: [
|
|
19422
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
19423
|
+
CustomToolbarButton,
|
|
19424
|
+
{
|
|
19425
|
+
type: "button",
|
|
19426
|
+
"aria-label": itemEditOn ? "Done editing this image" : "Edit this image",
|
|
19427
|
+
"aria-pressed": itemEditOn,
|
|
19428
|
+
onClick: onToggleItemEdit,
|
|
19429
|
+
className: "group size-8",
|
|
19430
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
19431
|
+
import_lucide_react9.Star,
|
|
19432
|
+
{
|
|
19433
|
+
size: 16,
|
|
19434
|
+
fill: "currentColor",
|
|
19435
|
+
strokeWidth: 0,
|
|
19436
|
+
className: cn(
|
|
19437
|
+
"transition-colors",
|
|
19438
|
+
itemEditOn ? "text-[#f59e0b] group-hover:text-[#d97706]" : "text-[#d6d3d1] group-hover:text-[#fbbf24]"
|
|
19439
|
+
),
|
|
19440
|
+
style: { pointerEvents: "none" }
|
|
19441
|
+
}
|
|
19442
|
+
)
|
|
19443
|
+
}
|
|
19444
|
+
) }),
|
|
19445
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(TooltipContent, { side: "bottom", sideOffset: 8, children: itemEditOn ? "Done editing this image" : "Edit this image" })
|
|
19446
|
+
] }),
|
|
19447
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(ToolbarSeparator, {}),
|
|
19448
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(ToolbarAction, { label: gatedLabel("Change image"), onClick: onChangeImage, disabled: !itemEditOn, children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_lucide_react9.Image, { size: 16, style: { pointerEvents: "none" } }) }),
|
|
19449
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(ToolbarAction, { label: gatedLabel("Link"), onClick: onOpenLink, disabled: !itemEditOn, children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_lucide_react9.Link, { size: 16, style: { pointerEvents: "none" } }) }),
|
|
19450
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(ToolbarAction, { label: gatedLabel("Move left"), onClick: onMoveLeft, disabled: !itemEditOn || index <= 0, children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_lucide_react9.ArrowLeft, { size: 16, style: { pointerEvents: "none" } }) }),
|
|
19451
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
19452
|
+
ToolbarAction,
|
|
19453
|
+
{
|
|
19454
|
+
label: gatedLabel("Move right"),
|
|
19455
|
+
onClick: onMoveRight,
|
|
19456
|
+
disabled: !itemEditOn || index >= itemCount - 1,
|
|
19457
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_lucide_react9.ArrowRight, { size: 16, style: { pointerEvents: "none" } })
|
|
19458
|
+
}
|
|
19459
|
+
),
|
|
19460
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(ToolbarAction, { label: gatedLabel("Remove image"), onClick: onRemoveItem, disabled: !itemEditOn || itemCount <= 1, children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_lucide_react9.ImageMinus, { size: 16, style: { pointerEvents: "none" } }) }),
|
|
19461
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(ToolbarSeparator, {}),
|
|
19462
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(OptionMenu, { label: "Layout", value: variant, options: VARIANTS, onChange: onSetVariant }),
|
|
19463
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(OptionMenu, { label: "Hover", value: hover, options: HOVERS, onChange: onSetHover }),
|
|
19464
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
19465
|
+
ToolbarAction,
|
|
19466
|
+
{
|
|
19467
|
+
label: treatment === "grayscale" ? "Show in color" : "Show grayscale",
|
|
19468
|
+
active: treatment === "grayscale",
|
|
19469
|
+
onClick: () => onSetTreatment(treatment === "grayscale" ? "color" : "grayscale"),
|
|
19470
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_lucide_react9.Palette, { size: 16, style: { pointerEvents: "none" } })
|
|
19471
|
+
}
|
|
19472
|
+
),
|
|
19473
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(ToolbarSeparator, {}),
|
|
19474
|
+
ALIGNS.map(({ value, label, Icon }) => /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(ToolbarAction, { label, active: align === value, onClick: () => onSetAlign(value), children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(Icon, { size: 16, style: { pointerEvents: "none" } }) }, value)),
|
|
19475
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(ToolbarSeparator, {}),
|
|
19476
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(ToolbarAction, { label: "Smaller", onClick: () => onResize(-8), children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_lucide_react9.Minus, { size: 16, style: { pointerEvents: "none" } }) }),
|
|
19477
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("span", { className: "min-w-[40px] text-center text-xs tabular-nums text-muted-foreground", children: [
|
|
19478
|
+
sizeValue,
|
|
19479
|
+
"px"
|
|
19480
|
+
] }),
|
|
19481
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(ToolbarAction, { label: "Larger", onClick: () => onResize(8), children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_lucide_react9.Plus, { size: 16, style: { pointerEvents: "none" } }) }),
|
|
19482
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(ToolbarSeparator, {}),
|
|
19483
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(ToolbarAction, { label: "Add image", onClick: onAddItem, children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_lucide_react9.ImagePlus, { size: 16, style: { pointerEvents: "none" } }) })
|
|
19484
|
+
]
|
|
19485
|
+
}
|
|
19486
|
+
),
|
|
19487
|
+
error && /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { className: "max-w-[260px] rounded-md bg-background px-2 py-1 text-center text-[11px] text-destructive shadow-sm", children: error })
|
|
19125
19488
|
]
|
|
19126
19489
|
}
|
|
19127
|
-
);
|
|
19490
|
+
) });
|
|
19128
19491
|
}
|
|
19129
19492
|
function findMediaStripSlots(tree) {
|
|
19130
19493
|
const stack = tree.rows.flatMap((row) => row.blocks);
|
|
@@ -19143,31 +19506,23 @@ function AiMediaStripOverlay({
|
|
|
19143
19506
|
}) {
|
|
19144
19507
|
const [hover, setHover] = (0, import_react10.useState)(null);
|
|
19145
19508
|
const [active, setActive] = (0, import_react10.useState)(null);
|
|
19509
|
+
const [itemEditOn, setItemEditOn] = (0, import_react10.useState)(false);
|
|
19510
|
+
const [linkOpen, setLinkOpen] = (0, import_react10.useState)(false);
|
|
19146
19511
|
const [pending, setPending] = (0, import_react10.useState)(false);
|
|
19147
19512
|
const [error, setError] = (0, import_react10.useState)(null);
|
|
19148
19513
|
const activeRef = (0, import_react10.useRef)(null);
|
|
19149
19514
|
activeRef.current = active;
|
|
19515
|
+
const linkOpenRef = (0, import_react10.useRef)(false);
|
|
19516
|
+
linkOpenRef.current = linkOpen;
|
|
19150
19517
|
(0, import_react10.useEffect)(() => {
|
|
19151
19518
|
const onMove = (e) => {
|
|
19519
|
+
const ref = itemRefFromTarget(e.target);
|
|
19152
19520
|
const t = e.target;
|
|
19153
|
-
|
|
19154
|
-
|
|
19155
|
-
|
|
19156
|
-
|
|
19157
|
-
|
|
19158
|
-
if (!itemEl) {
|
|
19159
|
-
setHover(null);
|
|
19160
|
-
return;
|
|
19161
|
-
}
|
|
19162
|
-
const sectionEl = itemEl.closest("[data-ohw-section]");
|
|
19163
|
-
const unit = sectionEl ? movableUnit(sectionEl) : null;
|
|
19164
|
-
const sectionId = unit ? instanceIdOf(unit) || null : null;
|
|
19165
|
-
const index = Number(itemEl.dataset.ohwMediaStripIndex);
|
|
19166
|
-
if (!sectionId || Number.isNaN(index)) {
|
|
19167
|
-
setHover(null);
|
|
19168
|
-
return;
|
|
19169
|
-
}
|
|
19170
|
-
setHover({ sectionId, index });
|
|
19521
|
+
const overEditable = Boolean(t?.closest?.("[data-ohw-editable]"));
|
|
19522
|
+
setHover((prev) => {
|
|
19523
|
+
const next = ref && !overEditable ? ref : null;
|
|
19524
|
+
return sameRef(prev, next) ? prev : next;
|
|
19525
|
+
});
|
|
19171
19526
|
};
|
|
19172
19527
|
const onLeave = () => setHover(null);
|
|
19173
19528
|
document.addEventListener("mousemove", onMove, { passive: true });
|
|
@@ -19179,23 +19534,25 @@ function AiMediaStripOverlay({
|
|
|
19179
19534
|
}, []);
|
|
19180
19535
|
(0, import_react10.useEffect)(() => {
|
|
19181
19536
|
const onClick = (e) => {
|
|
19182
|
-
const current = activeRef.current;
|
|
19183
|
-
if (!current) return;
|
|
19184
19537
|
const t = e.target;
|
|
19185
|
-
if (!(t instanceof
|
|
19186
|
-
if (t.closest(
|
|
19187
|
-
const
|
|
19188
|
-
if (
|
|
19189
|
-
|
|
19538
|
+
if (!(t instanceof Element)) return;
|
|
19539
|
+
if (t.closest(CHROME_SELECTOR)) return;
|
|
19540
|
+
const ref = itemRefFromTarget(t);
|
|
19541
|
+
if (sameRef(activeRef.current, ref)) return;
|
|
19542
|
+
if (ref) clearInteractionChromeRef.current();
|
|
19543
|
+
setItemEditOn(false);
|
|
19190
19544
|
setError(null);
|
|
19545
|
+
setActive(ref);
|
|
19191
19546
|
};
|
|
19192
19547
|
document.addEventListener("click", onClick, true);
|
|
19193
19548
|
return () => document.removeEventListener("click", onClick, true);
|
|
19194
|
-
}, []);
|
|
19549
|
+
}, [clearInteractionChromeRef]);
|
|
19195
19550
|
(0, import_react10.useEffect)(() => {
|
|
19196
19551
|
const onBlur = () => {
|
|
19197
19552
|
if (!activeRef.current) return;
|
|
19198
19553
|
setActive(null);
|
|
19554
|
+
setItemEditOn(false);
|
|
19555
|
+
setLinkOpen(false);
|
|
19199
19556
|
setError(null);
|
|
19200
19557
|
};
|
|
19201
19558
|
window.addEventListener("blur", onBlur);
|
|
@@ -19205,7 +19562,10 @@ function AiMediaStripOverlay({
|
|
|
19205
19562
|
const onKeyDown = (e) => {
|
|
19206
19563
|
if (e.key !== "Escape") return;
|
|
19207
19564
|
if (!activeRef.current) return;
|
|
19565
|
+
if (linkOpenRef.current) return;
|
|
19566
|
+
if (document.querySelector('[data-ohw-more-menu][data-state="open"]')) return;
|
|
19208
19567
|
setActive(null);
|
|
19568
|
+
setItemEditOn(false);
|
|
19209
19569
|
setError(null);
|
|
19210
19570
|
};
|
|
19211
19571
|
document.addEventListener("keydown", onKeyDown);
|
|
@@ -19239,137 +19599,133 @@ function AiMediaStripOverlay({
|
|
|
19239
19599
|
tree: nextTree,
|
|
19240
19600
|
label: entry.label,
|
|
19241
19601
|
media: extraMedia ? { ...entry.media, ...extraMedia } : entry.media,
|
|
19242
|
-
...entry.brand ? { brand: entry.brand } : {}
|
|
19602
|
+
...entry.brand ? { brand: entry.brand } : {},
|
|
19603
|
+
// The user is already looking at the strip they just edited — recentering the viewport
|
|
19604
|
+
// on every edit reads as the section jumping around.
|
|
19605
|
+
skipScrollIntoView: true
|
|
19243
19606
|
});
|
|
19244
19607
|
return true;
|
|
19245
19608
|
},
|
|
19246
19609
|
[findEntry, postToParent2, applyTreeLocalRef]
|
|
19247
19610
|
);
|
|
19248
19611
|
const activeEntry = active ? findEntry(active.sectionId) : null;
|
|
19249
|
-
const hoverHandleRect = useLiveItemRect(!active && hover ? hover : null);
|
|
19250
19612
|
const activeItemRect = useLiveItemRect(active);
|
|
19251
|
-
const
|
|
19252
|
-
const
|
|
19253
|
-
|
|
19254
|
-
|
|
19255
|
-
|
|
19256
|
-
|
|
19257
|
-
|
|
19258
|
-
|
|
19259
|
-
|
|
19260
|
-
|
|
19261
|
-
|
|
19262
|
-
|
|
19263
|
-
|
|
19264
|
-
|
|
19265
|
-
|
|
19266
|
-
|
|
19267
|
-
|
|
19268
|
-
|
|
19269
|
-
|
|
19270
|
-
|
|
19271
|
-
|
|
19272
|
-
|
|
19273
|
-
|
|
19274
|
-
|
|
19275
|
-
|
|
19276
|
-
|
|
19277
|
-
|
|
19278
|
-
|
|
19279
|
-
|
|
19280
|
-
|
|
19281
|
-
|
|
19282
|
-
|
|
19283
|
-
|
|
19284
|
-
|
|
19285
|
-
activeItemRect && active && activeEntry && /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
|
|
19286
|
-
ItemInteractionLayer,
|
|
19287
|
-
{
|
|
19288
|
-
rect: activeItemRect,
|
|
19289
|
-
state: toolbarState,
|
|
19290
|
-
toolbar: /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
|
|
19291
|
-
MediaStripToolbar,
|
|
19292
|
-
{
|
|
19293
|
-
entry: activeEntry,
|
|
19294
|
-
index: active.index,
|
|
19295
|
-
pending,
|
|
19296
|
-
error,
|
|
19297
|
-
onSetVariant: (variant) => runMutation(active.sectionId, (tree) => setMediaStripVariant(tree, variant)),
|
|
19298
|
-
onSetAlign: (align) => runMutation(active.sectionId, (tree) => setMediaStripAlign(tree, align)),
|
|
19299
|
-
onSetHover: (hoverPreset) => runMutation(active.sectionId, (tree) => setMediaStripHover(tree, hoverPreset)),
|
|
19300
|
-
onSetTreatment: (treatment) => runMutation(active.sectionId, (tree) => setMediaStripTreatment(tree, treatment)),
|
|
19301
|
-
onResize: (delta) => {
|
|
19302
|
-
const slots = findMediaStripSlots(activeEntry.tree);
|
|
19303
|
-
const variant = slots?.variant === "reel" ? "reel" : "logos";
|
|
19304
|
-
const current = variant === "logos" ? typeof slots?.logoMaxHeight === "number" ? slots.logoMaxHeight : 48 : typeof slots?.cardWidth === "number" ? slots.cardWidth : 240;
|
|
19305
|
-
void runMutation(active.sectionId, (tree) => setMediaStripSizing(tree, current + delta));
|
|
19306
|
-
},
|
|
19307
|
-
onSetAlt: (alt) => {
|
|
19308
|
-
void runMutation(active.sectionId, (tree) => setMediaStripItemAlt(tree, active.index, alt));
|
|
19309
|
-
},
|
|
19310
|
-
onSetLink: (href, linkTarget) => {
|
|
19613
|
+
const activeStripRect = useLiveItemRect(active, true);
|
|
19614
|
+
const hoverRect = useLiveItemRect(hover && !sameRef(hover, active) ? hover : null);
|
|
19615
|
+
const activeItems = activeEntry ? mediaStripItems(activeEntry.tree) : [];
|
|
19616
|
+
const activeItem = active ? activeItems[active.index] : void 0;
|
|
19617
|
+
const activeHref = activeItem?.href ?? "";
|
|
19618
|
+
const activeTarget = activeItem?.linkTarget === "same-tab" ? "same-tab" : "new-tab";
|
|
19619
|
+
return /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(import_jsx_runtime21.Fragment, { children: [
|
|
19620
|
+
hoverRect && /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(ItemInteractionLayer, { rect: hoverRect, state: "hover" }),
|
|
19621
|
+
activeItemRect && activeStripRect && active && activeEntry && /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(import_jsx_runtime21.Fragment, { children: [
|
|
19622
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(ItemInteractionLayer, { rect: activeItemRect, state: "active-top" }),
|
|
19623
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(StripToolbarSlot, { stripRect: activeStripRect, children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
19624
|
+
MediaStripToolbar,
|
|
19625
|
+
{
|
|
19626
|
+
entry: activeEntry,
|
|
19627
|
+
index: active.index,
|
|
19628
|
+
pending,
|
|
19629
|
+
error,
|
|
19630
|
+
itemEditOn,
|
|
19631
|
+
onToggleItemEdit: () => setItemEditOn((on) => !on),
|
|
19632
|
+
onSetVariant: (variant) => runMutation(active.sectionId, (tree) => setMediaStripVariant(tree, variant)),
|
|
19633
|
+
onSetAlign: (align) => runMutation(active.sectionId, (tree) => setMediaStripAlign(tree, align)),
|
|
19634
|
+
onSetHover: (hoverPreset) => runMutation(active.sectionId, (tree) => setMediaStripHover(tree, hoverPreset)),
|
|
19635
|
+
onSetTreatment: (treatment) => runMutation(active.sectionId, (tree) => setMediaStripTreatment(tree, treatment)),
|
|
19636
|
+
onResize: (delta) => {
|
|
19637
|
+
const slots = findMediaStripSlots(activeEntry.tree);
|
|
19638
|
+
const variant = slots?.variant === "reel" ? "reel" : "logos";
|
|
19639
|
+
const current = variant === "logos" ? typeof slots?.logoMaxHeight === "number" ? slots.logoMaxHeight : 48 : typeof slots?.cardWidth === "number" ? slots.cardWidth : 240;
|
|
19640
|
+
void runMutation(active.sectionId, (tree) => setMediaStripSizing(tree, current + delta));
|
|
19641
|
+
},
|
|
19642
|
+
onOpenLink: () => setLinkOpen(true),
|
|
19643
|
+
onAddItem: () => {
|
|
19644
|
+
void requestAssetPick(postToParent2).then((picked) => {
|
|
19645
|
+
if (!picked) return;
|
|
19646
|
+
const item = { assetId: picked.assetId, alt: "Logo" };
|
|
19311
19647
|
void runMutation(
|
|
19312
19648
|
active.sectionId,
|
|
19313
|
-
(tree) =>
|
|
19314
|
-
|
|
19315
|
-
|
|
19316
|
-
|
|
19317
|
-
void requestAssetPick(postToParent2).then((picked) => {
|
|
19318
|
-
if (!picked) return;
|
|
19319
|
-
const item = { assetId: picked.assetId, alt: "Logo" };
|
|
19320
|
-
void runMutation(
|
|
19321
|
-
active.sectionId,
|
|
19322
|
-
(tree) => addMediaStripItem(tree, item, active.index),
|
|
19323
|
-
{ [picked.assetId]: picked.url }
|
|
19324
|
-
).then((applied) => {
|
|
19325
|
-
if (applied) setActive({ sectionId: active.sectionId, index: active.index + 1 });
|
|
19326
|
-
});
|
|
19649
|
+
(tree) => addMediaStripItem(tree, item, active.index),
|
|
19650
|
+
{ [picked.assetId]: picked.url }
|
|
19651
|
+
).then((applied) => {
|
|
19652
|
+
if (applied) setActive({ sectionId: active.sectionId, index: active.index + 1 });
|
|
19327
19653
|
});
|
|
19328
|
-
}
|
|
19329
|
-
|
|
19330
|
-
|
|
19331
|
-
|
|
19332
|
-
|
|
19333
|
-
|
|
19334
|
-
|
|
19335
|
-
|
|
19336
|
-
|
|
19337
|
-
});
|
|
19338
|
-
},
|
|
19339
|
-
onRemoveItem: () => {
|
|
19340
|
-
void runMutation(active.sectionId, (tree) => removeMediaStripItem(tree, active.index)).then(
|
|
19341
|
-
(applied) => {
|
|
19342
|
-
if (applied) setActive(null);
|
|
19343
|
-
}
|
|
19344
|
-
);
|
|
19345
|
-
},
|
|
19346
|
-
onMoveLeft: () => {
|
|
19347
|
-
void runMutation(active.sectionId, (tree) => reorderMediaStripItem(tree, active.index, -1)).then(
|
|
19348
|
-
(applied) => {
|
|
19349
|
-
if (applied) setActive({ sectionId: active.sectionId, index: active.index - 1 });
|
|
19350
|
-
}
|
|
19351
|
-
);
|
|
19352
|
-
},
|
|
19353
|
-
onMoveRight: () => {
|
|
19354
|
-
void runMutation(active.sectionId, (tree) => reorderMediaStripItem(tree, active.index, 1)).then(
|
|
19355
|
-
(applied) => {
|
|
19356
|
-
if (applied) setActive({ sectionId: active.sectionId, index: active.index + 1 });
|
|
19357
|
-
}
|
|
19654
|
+
});
|
|
19655
|
+
},
|
|
19656
|
+
onChangeImage: () => {
|
|
19657
|
+
void requestAssetPick(postToParent2).then((picked) => {
|
|
19658
|
+
if (!picked) return;
|
|
19659
|
+
void runMutation(
|
|
19660
|
+
active.sectionId,
|
|
19661
|
+
(tree) => setMediaStripItemAsset(tree, active.index, picked.assetId),
|
|
19662
|
+
{ [picked.assetId]: picked.url }
|
|
19358
19663
|
);
|
|
19359
|
-
}
|
|
19664
|
+
});
|
|
19665
|
+
},
|
|
19666
|
+
onRemoveItem: () => {
|
|
19667
|
+
void runMutation(active.sectionId, (tree) => removeMediaStripItem(tree, active.index)).then(
|
|
19668
|
+
(applied) => {
|
|
19669
|
+
if (applied) setActive(null);
|
|
19670
|
+
}
|
|
19671
|
+
);
|
|
19672
|
+
},
|
|
19673
|
+
onMoveLeft: () => {
|
|
19674
|
+
void runMutation(active.sectionId, (tree) => reorderMediaStripItem(tree, active.index, -1)).then(
|
|
19675
|
+
(applied) => {
|
|
19676
|
+
if (applied) setActive({ sectionId: active.sectionId, index: active.index - 1 });
|
|
19677
|
+
}
|
|
19678
|
+
);
|
|
19679
|
+
},
|
|
19680
|
+
onMoveRight: () => {
|
|
19681
|
+
void runMutation(active.sectionId, (tree) => reorderMediaStripItem(tree, active.index, 1)).then(
|
|
19682
|
+
(applied) => {
|
|
19683
|
+
if (applied) setActive({ sectionId: active.sectionId, index: active.index + 1 });
|
|
19684
|
+
}
|
|
19685
|
+
);
|
|
19360
19686
|
}
|
|
19361
|
-
|
|
19362
|
-
}
|
|
19363
|
-
|
|
19687
|
+
}
|
|
19688
|
+
) }),
|
|
19689
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
19690
|
+
"div",
|
|
19691
|
+
{
|
|
19692
|
+
"data-ohw-bridge": "",
|
|
19693
|
+
"data-ohw-item-interaction": "",
|
|
19694
|
+
"aria-hidden": true,
|
|
19695
|
+
className: "pointer-events-none fixed rounded-[4px] px-[7px] py-[3px] font-sans text-[11px] font-medium leading-none text-primary-foreground whitespace-nowrap",
|
|
19696
|
+
style: {
|
|
19697
|
+
top: activeItemRect.top + activeItemRect.height + 10,
|
|
19698
|
+
left: activeItemRect.left - 5,
|
|
19699
|
+
background: PRIMARY3,
|
|
19700
|
+
zIndex: 2147483644
|
|
19701
|
+
},
|
|
19702
|
+
children: "Media item"
|
|
19703
|
+
}
|
|
19704
|
+
),
|
|
19705
|
+
linkOpen && /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
19706
|
+
LinkModal,
|
|
19707
|
+
{
|
|
19708
|
+
href: activeHref,
|
|
19709
|
+
linkTarget: activeTarget,
|
|
19710
|
+
onClose: () => setLinkOpen(false),
|
|
19711
|
+
onSave: (href, linkTarget) => {
|
|
19712
|
+
void runMutation(
|
|
19713
|
+
active.sectionId,
|
|
19714
|
+
(tree) => setMediaStripItemLink(tree, active.index, href ? { href, linkTarget } : {})
|
|
19715
|
+
);
|
|
19716
|
+
}
|
|
19717
|
+
}
|
|
19718
|
+
)
|
|
19719
|
+
] })
|
|
19364
19720
|
] });
|
|
19365
19721
|
}
|
|
19366
19722
|
|
|
19367
19723
|
// src/ui/ai-section/AiPricingCardOverlay.tsx
|
|
19368
19724
|
var import_react11 = require("react");
|
|
19369
|
-
var
|
|
19370
|
-
var
|
|
19725
|
+
var import_lucide_react10 = require("lucide-react");
|
|
19726
|
+
var import_jsx_runtime22 = require("react/jsx-runtime");
|
|
19371
19727
|
var PRIMARY4 = "var(--ohw-primary, #0885FE)";
|
|
19372
|
-
var
|
|
19728
|
+
var CHROME_SELECTOR2 = "[data-ohw-toolbar], [data-ohw-edit-chrome], [data-ohw-item-interaction], [data-ohw-link-modal-root], [data-ohw-section-picker], [data-ohw-ai-review], [data-ohw-more-menu]";
|
|
19373
19729
|
function findPricingCardElement(sectionId, index) {
|
|
19374
19730
|
const sectionEl = findByInstanceId(sectionId);
|
|
19375
19731
|
if (!sectionEl) return null;
|
|
@@ -19381,7 +19737,7 @@ function findPricingCardElement(sectionId, index) {
|
|
|
19381
19737
|
}
|
|
19382
19738
|
function cardRefFromTarget(target) {
|
|
19383
19739
|
if (!(target instanceof Element)) return null;
|
|
19384
|
-
if (target.closest(
|
|
19740
|
+
if (target.closest(CHROME_SELECTOR2)) return null;
|
|
19385
19741
|
const cardEl = target.closest("[data-ohw-pricing-card]");
|
|
19386
19742
|
if (!cardEl) return null;
|
|
19387
19743
|
const sectionEl = cardEl.closest("[data-ohw-section]");
|
|
@@ -19391,21 +19747,21 @@ function cardRefFromTarget(target) {
|
|
|
19391
19747
|
if (!sectionId || Number.isNaN(index)) return null;
|
|
19392
19748
|
return { sectionId, index };
|
|
19393
19749
|
}
|
|
19394
|
-
function
|
|
19750
|
+
function sameRef2(a, b) {
|
|
19395
19751
|
return a?.sectionId === b?.sectionId && a?.index === b?.index;
|
|
19396
19752
|
}
|
|
19397
|
-
function
|
|
19753
|
+
function rectOf2(el) {
|
|
19398
19754
|
if (!el) return null;
|
|
19399
19755
|
const r2 = el.getBoundingClientRect();
|
|
19400
19756
|
if (r2.width <= 0 || r2.height <= 0) return null;
|
|
19401
19757
|
return { top: r2.top, left: r2.left, width: r2.width, height: r2.height };
|
|
19402
19758
|
}
|
|
19403
19759
|
function readRect3(ref) {
|
|
19404
|
-
return
|
|
19760
|
+
return rectOf2(ref && findPricingCardElement(ref.sectionId, ref.index));
|
|
19405
19761
|
}
|
|
19406
19762
|
function readGridRect(ref) {
|
|
19407
19763
|
const card = ref && findPricingCardElement(ref.sectionId, ref.index);
|
|
19408
|
-
return
|
|
19764
|
+
return rectOf2(card?.closest("[data-ohw-pricing-collection]") ?? card);
|
|
19409
19765
|
}
|
|
19410
19766
|
function useLiveCardRect(ref, grid = false) {
|
|
19411
19767
|
const [rect, setRect] = (0, import_react11.useState)(null);
|
|
@@ -19435,7 +19791,7 @@ function useLiveCardRect(ref, grid = false) {
|
|
|
19435
19791
|
}
|
|
19436
19792
|
var TOOLBAR_GRID_GAP = 52;
|
|
19437
19793
|
var TOOLBAR_GRID_GAP_MOBILE = 42;
|
|
19438
|
-
var
|
|
19794
|
+
var TOOLBAR_EDGE_MARGIN3 = 4;
|
|
19439
19795
|
function GridToolbarSlot({ gridRect, children }) {
|
|
19440
19796
|
const slotRef = (0, import_react11.useRef)(null);
|
|
19441
19797
|
const [shift, setShift] = (0, import_react11.useState)(0);
|
|
@@ -19447,7 +19803,7 @@ function GridToolbarSlot({ gridRect, children }) {
|
|
|
19447
19803
|
const w = slot.offsetWidth;
|
|
19448
19804
|
if (w <= 0) return;
|
|
19449
19805
|
const half = w / 2;
|
|
19450
|
-
const clamped = Math.max(
|
|
19806
|
+
const clamped = Math.max(TOOLBAR_EDGE_MARGIN3 + half, Math.min(centerX, window.innerWidth - TOOLBAR_EDGE_MARGIN3 - half));
|
|
19451
19807
|
setShift((prev) => Math.abs(prev - (clamped - centerX)) < 0.5 ? prev : clamped - centerX);
|
|
19452
19808
|
};
|
|
19453
19809
|
clamp();
|
|
@@ -19456,7 +19812,7 @@ function GridToolbarSlot({ gridRect, children }) {
|
|
|
19456
19812
|
return () => ro.disconnect();
|
|
19457
19813
|
}, [centerX, children]);
|
|
19458
19814
|
const mobile = window.innerWidth <= 480;
|
|
19459
|
-
return /* @__PURE__ */ (0,
|
|
19815
|
+
return /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
|
|
19460
19816
|
"div",
|
|
19461
19817
|
{
|
|
19462
19818
|
ref: slotRef,
|
|
@@ -19491,7 +19847,7 @@ function requestValidateTree2(postToParent2, tree) {
|
|
|
19491
19847
|
});
|
|
19492
19848
|
}
|
|
19493
19849
|
function StyleSwatch({ style }) {
|
|
19494
|
-
return /* @__PURE__ */ (0,
|
|
19850
|
+
return /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
|
|
19495
19851
|
"span",
|
|
19496
19852
|
{
|
|
19497
19853
|
"aria-hidden": true,
|
|
@@ -19505,35 +19861,35 @@ function StyleSwatch({ style }) {
|
|
|
19505
19861
|
);
|
|
19506
19862
|
}
|
|
19507
19863
|
function ButtonGlyph() {
|
|
19508
|
-
return /* @__PURE__ */ (0,
|
|
19509
|
-
/* @__PURE__ */ (0,
|
|
19510
|
-
/* @__PURE__ */ (0,
|
|
19864
|
+
return /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("svg", { width: "18", height: "12", viewBox: "0 0 18 12", fill: "none", "aria-hidden": true, style: { pointerEvents: "none" }, children: [
|
|
19865
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)("rect", { x: "0.75", y: "0.75", width: "16.5", height: "10.5", rx: "3", stroke: "currentColor", strokeWidth: "1.5" }),
|
|
19866
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)("path", { d: "M5.5 6H12.5", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round" })
|
|
19511
19867
|
] });
|
|
19512
19868
|
}
|
|
19513
19869
|
function FeatureGlyph({ mode }) {
|
|
19514
|
-
return /* @__PURE__ */ (0,
|
|
19515
|
-
/* @__PURE__ */ (0,
|
|
19516
|
-
/* @__PURE__ */ (0,
|
|
19517
|
-
/* @__PURE__ */ (0,
|
|
19518
|
-
/* @__PURE__ */ (0,
|
|
19519
|
-
/* @__PURE__ */ (0,
|
|
19520
|
-
mode === "add" && /* @__PURE__ */ (0,
|
|
19870
|
+
return /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("svg", { width: "18", height: "18", viewBox: "0 0 18 18", fill: "none", "aria-hidden": true, style: { pointerEvents: "none" }, children: [
|
|
19871
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)("circle", { cx: "8", cy: "8", r: "7.25", stroke: "currentColor", strokeWidth: "1.5" }),
|
|
19872
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)("path", { d: "M5 8.2L7.2 10.3L11 6", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round" }),
|
|
19873
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)("circle", { cx: "13.5", cy: "13.5", r: "4.25", fill: "var(--ohw-background, #ffffff)", stroke: "var(--ohw-background, #ffffff)", strokeWidth: "1" }),
|
|
19874
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)("circle", { cx: "13.5", cy: "13.5", r: "3.75", fill: "var(--ohw-background, #ffffff)", stroke: PRIMARY4, strokeWidth: "1" }),
|
|
19875
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)("path", { d: "M11.5 13.5H15.5", stroke: PRIMARY4, strokeWidth: "1.5", strokeLinecap: "round" }),
|
|
19876
|
+
mode === "add" && /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("path", { d: "M13.5 11.5V15.5", stroke: PRIMARY4, strokeWidth: "1.5", strokeLinecap: "round" })
|
|
19521
19877
|
] });
|
|
19522
19878
|
}
|
|
19523
|
-
function
|
|
19879
|
+
function ToolbarAction2({
|
|
19524
19880
|
label,
|
|
19525
19881
|
onClick,
|
|
19526
19882
|
disabled = false,
|
|
19527
19883
|
children
|
|
19528
19884
|
}) {
|
|
19529
|
-
const button = /* @__PURE__ */ (0,
|
|
19530
|
-
return /* @__PURE__ */ (0,
|
|
19531
|
-
/* @__PURE__ */ (0,
|
|
19532
|
-
/* @__PURE__ */ (0,
|
|
19885
|
+
const button = /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(CustomToolbarButton, { type: "button", "aria-label": label, disabled, onClick, className: "size-8", children });
|
|
19886
|
+
return /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(Tooltip, { children: [
|
|
19887
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)(TooltipTrigger, { asChild: true, children: disabled ? /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("span", { className: "inline-flex", children: button }) : button }),
|
|
19888
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)(TooltipContent, { side: "bottom", sideOffset: 8, children: label })
|
|
19533
19889
|
] });
|
|
19534
19890
|
}
|
|
19535
|
-
function
|
|
19536
|
-
return /* @__PURE__ */ (0,
|
|
19891
|
+
function ToolbarSeparator2() {
|
|
19892
|
+
return /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("span", { "aria-hidden": true, className: "mx-0.5 block h-6 w-px shrink-0 bg-border" });
|
|
19537
19893
|
}
|
|
19538
19894
|
function CardStyleMenu({
|
|
19539
19895
|
value,
|
|
@@ -19541,7 +19897,7 @@ function CardStyleMenu({
|
|
|
19541
19897
|
disabled = false
|
|
19542
19898
|
}) {
|
|
19543
19899
|
const current = PRICING_CARD_STYLES.find((s) => s.value === value) ?? PRICING_CARD_STYLES[0];
|
|
19544
|
-
const trigger = /* @__PURE__ */ (0,
|
|
19900
|
+
const trigger = /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(
|
|
19545
19901
|
"button",
|
|
19546
19902
|
{
|
|
19547
19903
|
type: "button",
|
|
@@ -19552,28 +19908,28 @@ function CardStyleMenu({
|
|
|
19552
19908
|
disabled && "cursor-not-allowed opacity-40 hover:bg-transparent"
|
|
19553
19909
|
),
|
|
19554
19910
|
children: [
|
|
19555
|
-
/* @__PURE__ */ (0,
|
|
19556
|
-
/* @__PURE__ */ (0,
|
|
19557
|
-
/* @__PURE__ */ (0,
|
|
19911
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)(StyleSwatch, { style: current.value }),
|
|
19912
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)("span", { className: "flex-1 text-left", children: current.label }),
|
|
19913
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)(import_lucide_react10.ChevronDown, { size: 16, style: { pointerEvents: "none" } })
|
|
19558
19914
|
]
|
|
19559
19915
|
}
|
|
19560
19916
|
);
|
|
19561
19917
|
if (disabled) {
|
|
19562
|
-
return /* @__PURE__ */ (0,
|
|
19563
|
-
/* @__PURE__ */ (0,
|
|
19564
|
-
/* @__PURE__ */ (0,
|
|
19565
|
-
/* @__PURE__ */ (0,
|
|
19566
|
-
/* @__PURE__ */ (0,
|
|
19918
|
+
return /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("div", { className: "flex items-center gap-1.5 pl-1.5", children: [
|
|
19919
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)("span", { className: "text-xs text-muted-foreground opacity-50", children: "Card style" }),
|
|
19920
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(Tooltip, { children: [
|
|
19921
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("span", { className: "inline-flex", children: trigger }) }),
|
|
19922
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)(TooltipContent, { side: "bottom", sideOffset: 8, children: "Mark as featured to edit card style" })
|
|
19567
19923
|
] })
|
|
19568
19924
|
] });
|
|
19569
19925
|
}
|
|
19570
|
-
return /* @__PURE__ */ (0,
|
|
19571
|
-
/* @__PURE__ */ (0,
|
|
19572
|
-
/* @__PURE__ */ (0,
|
|
19573
|
-
/* @__PURE__ */ (0,
|
|
19574
|
-
/* @__PURE__ */ (0,
|
|
19926
|
+
return /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("div", { className: "flex items-center gap-1.5 pl-1.5", children: [
|
|
19927
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)("span", { className: "text-xs text-muted-foreground", children: "Card style" }),
|
|
19928
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(DropdownMenu, { modal: false, children: [
|
|
19929
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)(DropdownMenuTrigger, { asChild: true, children: trigger }),
|
|
19930
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)(DropdownMenuContent, { align: "end", sideOffset: 8, className: "w-[152px] min-w-[152px] p-1", children: PRICING_CARD_STYLES.map((style) => {
|
|
19575
19931
|
const selected = style.value === value;
|
|
19576
|
-
return /* @__PURE__ */ (0,
|
|
19932
|
+
return /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(
|
|
19577
19933
|
DropdownMenuItem,
|
|
19578
19934
|
{
|
|
19579
19935
|
role: "menuitemradio",
|
|
@@ -19581,9 +19937,9 @@ function CardStyleMenu({
|
|
|
19581
19937
|
onSelect: () => onChange(style.value),
|
|
19582
19938
|
className: cn("grid grid-cols-[18px_1fr_16px] gap-2 py-2 pl-2 pr-2 text-[13px]", selected && "bg-muted"),
|
|
19583
19939
|
children: [
|
|
19584
|
-
/* @__PURE__ */ (0,
|
|
19585
|
-
/* @__PURE__ */ (0,
|
|
19586
|
-
selected && /* @__PURE__ */ (0,
|
|
19940
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)(StyleSwatch, { style: style.value }),
|
|
19941
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)("span", { children: style.label }),
|
|
19942
|
+
selected && /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(import_lucide_react10.Check, { size: 16, className: "text-bridge-primary" })
|
|
19587
19943
|
]
|
|
19588
19944
|
},
|
|
19589
19945
|
style.value
|
|
@@ -19613,7 +19969,7 @@ function PricingCardToolbar({
|
|
|
19613
19969
|
const style = pricingCardStyle(entry.tree, index);
|
|
19614
19970
|
const featuredTag = pricingCardFeaturedTag(entry.tree, index);
|
|
19615
19971
|
const mobile = window.innerWidth <= 480;
|
|
19616
|
-
return /* @__PURE__ */ (0,
|
|
19972
|
+
return /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(TooltipProvider, { delayDuration: 0, children: /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(
|
|
19617
19973
|
"div",
|
|
19618
19974
|
{
|
|
19619
19975
|
"data-ohw-bridge": "",
|
|
@@ -19625,7 +19981,7 @@ function PricingCardToolbar({
|
|
|
19625
19981
|
),
|
|
19626
19982
|
style: { maxWidth: mobile ? "calc(100vw - 24px)" : void 0 },
|
|
19627
19983
|
children: [
|
|
19628
|
-
/* @__PURE__ */ (0,
|
|
19984
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(
|
|
19629
19985
|
"div",
|
|
19630
19986
|
{
|
|
19631
19987
|
className: cn(
|
|
@@ -19634,8 +19990,8 @@ function PricingCardToolbar({
|
|
|
19634
19990
|
mobile ? "flex-wrap justify-center" : "flex-nowrap"
|
|
19635
19991
|
),
|
|
19636
19992
|
children: [
|
|
19637
|
-
/* @__PURE__ */ (0,
|
|
19638
|
-
/* @__PURE__ */ (0,
|
|
19993
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(Tooltip, { children: [
|
|
19994
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
|
|
19639
19995
|
CustomToolbarButton,
|
|
19640
19996
|
{
|
|
19641
19997
|
type: "button",
|
|
@@ -19643,8 +19999,8 @@ function PricingCardToolbar({
|
|
|
19643
19999
|
"aria-pressed": featuredTag,
|
|
19644
20000
|
onClick: () => onSetFeaturedTag(!featuredTag),
|
|
19645
20001
|
className: "group size-8",
|
|
19646
|
-
children: /* @__PURE__ */ (0,
|
|
19647
|
-
|
|
20002
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
|
|
20003
|
+
import_lucide_react10.Star,
|
|
19648
20004
|
{
|
|
19649
20005
|
size: 16,
|
|
19650
20006
|
fill: "currentColor",
|
|
@@ -19658,25 +20014,25 @@ function PricingCardToolbar({
|
|
|
19658
20014
|
)
|
|
19659
20015
|
}
|
|
19660
20016
|
) }),
|
|
19661
|
-
/* @__PURE__ */ (0,
|
|
20017
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)(TooltipContent, { side: "bottom", sideOffset: 8, children: featuredTag ? "Unmark featured" : "Mark as featured" })
|
|
19662
20018
|
] }),
|
|
19663
|
-
/* @__PURE__ */ (0,
|
|
19664
|
-
/* @__PURE__ */ (0,
|
|
19665
|
-
/* @__PURE__ */ (0,
|
|
19666
|
-
/* @__PURE__ */ (0,
|
|
19667
|
-
/* @__PURE__ */ (0,
|
|
19668
|
-
/* @__PURE__ */ (0,
|
|
19669
|
-
/* @__PURE__ */ (0,
|
|
20019
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)(ToolbarSeparator2, {}),
|
|
20020
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)(CardStyleMenu, { value: style, onChange: onSetStyle, disabled: !featuredTag }),
|
|
20021
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)(ToolbarSeparator2, {}),
|
|
20022
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)(ToolbarAction2, { label: "Add button", onClick: onAddButton, disabled: buttonCount >= 2, children: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(ButtonGlyph, {}) }),
|
|
20023
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)(ToolbarAction2, { label: "Remove button", onClick: onRemoveButton, disabled: buttonCount === 0, children: /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("span", { className: "relative inline-flex", children: [
|
|
20024
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)(ButtonGlyph, {}),
|
|
20025
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)(import_lucide_react10.Minus, { size: 10, strokeWidth: 2.5, className: "absolute -right-1.5 -top-1.5 rounded-full bg-background text-bridge-primary" })
|
|
19670
20026
|
] }) }),
|
|
19671
|
-
/* @__PURE__ */ (0,
|
|
19672
|
-
/* @__PURE__ */ (0,
|
|
19673
|
-
/* @__PURE__ */ (0,
|
|
19674
|
-
/* @__PURE__ */ (0,
|
|
19675
|
-
/* @__PURE__ */ (0,
|
|
20027
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)(ToolbarAction2, { label: "Add feature", onClick: onAddFeature, disabled: featureCount >= 10, children: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(FeatureGlyph, { mode: "add" }) }),
|
|
20028
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)(ToolbarAction2, { label: "Remove feature", onClick: onRemoveFeature, disabled: featureCount <= 1, children: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(FeatureGlyph, { mode: "remove" }) }),
|
|
20029
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)(ToolbarSeparator2, {}),
|
|
20030
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)(ToolbarAction2, { label: "Add tier", onClick: onAddTier, disabled: collectionCount >= 4, children: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(import_lucide_react10.Plus, { size: 16, style: { pointerEvents: "none" } }) }),
|
|
20031
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)(ToolbarAction2, { label: "Remove tier", onClick: onRemoveTier, disabled: collectionCount <= 1, children: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(import_lucide_react10.Minus, { size: 16, style: { pointerEvents: "none" } }) })
|
|
19676
20032
|
]
|
|
19677
20033
|
}
|
|
19678
20034
|
),
|
|
19679
|
-
error && /* @__PURE__ */ (0,
|
|
20035
|
+
error && /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("div", { className: "max-w-[260px] rounded-md bg-background px-2 py-1 text-center text-[11px] text-destructive shadow-sm", children: error })
|
|
19680
20036
|
]
|
|
19681
20037
|
}
|
|
19682
20038
|
) });
|
|
@@ -19710,7 +20066,7 @@ function AiPricingCardOverlay({
|
|
|
19710
20066
|
const overEditable = Boolean(t?.closest?.("[data-ohw-editable], [data-ohw-role], a, button"));
|
|
19711
20067
|
setHover((prev) => {
|
|
19712
20068
|
const next = ref && !overEditable ? ref : null;
|
|
19713
|
-
return
|
|
20069
|
+
return sameRef2(prev, next) ? prev : next;
|
|
19714
20070
|
});
|
|
19715
20071
|
};
|
|
19716
20072
|
const onLeave = () => setHover(null);
|
|
@@ -19725,10 +20081,10 @@ function AiPricingCardOverlay({
|
|
|
19725
20081
|
const onClick = (e) => {
|
|
19726
20082
|
const t = e.target;
|
|
19727
20083
|
if (!(t instanceof Element)) return;
|
|
19728
|
-
if (t.closest(
|
|
20084
|
+
if (t.closest(CHROME_SELECTOR2)) return;
|
|
19729
20085
|
const ref = cardRefFromTarget(t);
|
|
19730
|
-
setActive((prev) =>
|
|
19731
|
-
if (!ref || !
|
|
20086
|
+
setActive((prev) => sameRef2(prev, ref) ? prev : ref);
|
|
20087
|
+
if (!ref || !sameRef2(activeRef.current, ref)) setError(null);
|
|
19732
20088
|
};
|
|
19733
20089
|
document.addEventListener("click", onClick, true);
|
|
19734
20090
|
return () => document.removeEventListener("click", onClick, true);
|
|
@@ -19792,13 +20148,13 @@ function AiPricingCardOverlay({
|
|
|
19792
20148
|
);
|
|
19793
20149
|
const activeEntry = active ? findEntry(active.sectionId) : null;
|
|
19794
20150
|
const activeCardRect = useLiveCardRect(active);
|
|
19795
|
-
const activeGridRect = useLiveCardRect(active, true);
|
|
19796
|
-
const hoverRect = useLiveCardRect(hover && !
|
|
19797
|
-
return /* @__PURE__ */ (0,
|
|
19798
|
-
hoverRect && /* @__PURE__ */ (0,
|
|
19799
|
-
activeCardRect && activeGridRect && active && activeEntry && /* @__PURE__ */ (0,
|
|
19800
|
-
/* @__PURE__ */ (0,
|
|
19801
|
-
/* @__PURE__ */ (0,
|
|
20151
|
+
const activeGridRect = useLiveCardRect(active, true);
|
|
20152
|
+
const hoverRect = useLiveCardRect(hover && !sameRef2(hover, active) ? hover : null);
|
|
20153
|
+
return /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(import_jsx_runtime22.Fragment, { children: [
|
|
20154
|
+
hoverRect && /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(ItemInteractionLayer, { rect: hoverRect, state: "hover" }),
|
|
20155
|
+
activeCardRect && activeGridRect && active && activeEntry && /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(import_jsx_runtime22.Fragment, { children: [
|
|
20156
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)(ItemInteractionLayer, { rect: activeCardRect, state: "active-top" }),
|
|
20157
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)(GridToolbarSlot, { gridRect: activeGridRect, children: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
|
|
19802
20158
|
PricingCardToolbar,
|
|
19803
20159
|
{
|
|
19804
20160
|
entry: activeEntry,
|
|
@@ -19826,7 +20182,7 @@ function AiPricingCardOverlay({
|
|
|
19826
20182
|
onRemoveFeature: () => runMutation(active.sectionId, (tree) => removePricingCardFeature(tree, active.index))
|
|
19827
20183
|
}
|
|
19828
20184
|
) }),
|
|
19829
|
-
/* @__PURE__ */ (0,
|
|
20185
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
|
|
19830
20186
|
"div",
|
|
19831
20187
|
{
|
|
19832
20188
|
"data-ohw-bridge": "",
|
|
@@ -19848,7 +20204,7 @@ function AiPricingCardOverlay({
|
|
|
19848
20204
|
|
|
19849
20205
|
// src/ui/ai-section/AiVideoOverlay.tsx
|
|
19850
20206
|
var import_react12 = require("react");
|
|
19851
|
-
var
|
|
20207
|
+
var import_lucide_react11 = require("lucide-react");
|
|
19852
20208
|
|
|
19853
20209
|
// src/lib/ai-video-tree.ts
|
|
19854
20210
|
function resolveVideoBlock(tree, path) {
|
|
@@ -19919,10 +20275,10 @@ function extractYouTubeId(input) {
|
|
|
19919
20275
|
}
|
|
19920
20276
|
|
|
19921
20277
|
// src/ui/ai-section/AiVideoOverlay.tsx
|
|
19922
|
-
var
|
|
20278
|
+
var import_jsx_runtime23 = require("react/jsx-runtime");
|
|
19923
20279
|
var PRIMARY5 = "#0885FE";
|
|
19924
|
-
var
|
|
19925
|
-
var
|
|
20280
|
+
var OHW_BLUE = `var(--ohw-primary, ${PRIMARY5})`;
|
|
20281
|
+
var OHW_BLUE_DARK = `color-mix(in srgb, var(--ohw-primary, ${PRIMARY5}) 60%, #000000)`;
|
|
19926
20282
|
function findVideoBlockElement(sectionId, path) {
|
|
19927
20283
|
const sectionEl = findByInstanceId(sectionId);
|
|
19928
20284
|
if (!sectionEl) return null;
|
|
@@ -19982,12 +20338,12 @@ function requestValidateTree3(postToParent2, tree) {
|
|
|
19982
20338
|
postToParent2({ type: "ow:ai-validate-tree-request", id, tree });
|
|
19983
20339
|
});
|
|
19984
20340
|
}
|
|
19985
|
-
function
|
|
20341
|
+
function Pill({
|
|
19986
20342
|
label,
|
|
19987
20343
|
onClick,
|
|
19988
20344
|
disabled
|
|
19989
20345
|
}) {
|
|
19990
|
-
return /* @__PURE__ */ (0,
|
|
20346
|
+
return /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
|
|
19991
20347
|
"button",
|
|
19992
20348
|
{
|
|
19993
20349
|
type: "button",
|
|
@@ -20003,7 +20359,7 @@ function Pill2({
|
|
|
20003
20359
|
border: "none",
|
|
20004
20360
|
cursor: disabled ? "default" : "pointer",
|
|
20005
20361
|
background: "#ffffff",
|
|
20006
|
-
color:
|
|
20362
|
+
color: OHW_BLUE_DARK,
|
|
20007
20363
|
opacity: disabled ? 0.4 : 1,
|
|
20008
20364
|
fontSize: 12,
|
|
20009
20365
|
lineHeight: "16px",
|
|
@@ -20025,7 +20381,7 @@ function VideoUrlInput({ value, onCommit }) {
|
|
|
20025
20381
|
setDraft(value ? watchUrl(value) : "");
|
|
20026
20382
|
setInvalid(false);
|
|
20027
20383
|
}, [value]);
|
|
20028
|
-
const
|
|
20384
|
+
const commit2 = () => {
|
|
20029
20385
|
const next = draft.trim();
|
|
20030
20386
|
if (!next) {
|
|
20031
20387
|
setInvalid(false);
|
|
@@ -20046,8 +20402,8 @@ function VideoUrlInput({ value, onCommit }) {
|
|
|
20046
20402
|
onCommit(id);
|
|
20047
20403
|
}
|
|
20048
20404
|
};
|
|
20049
|
-
return /* @__PURE__ */ (0,
|
|
20050
|
-
/* @__PURE__ */ (0,
|
|
20405
|
+
return /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { style: { display: "flex", flexDirection: "column", gap: 4, width: "100%", maxWidth: 280 }, children: [
|
|
20406
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsxs)(
|
|
20051
20407
|
"div",
|
|
20052
20408
|
{
|
|
20053
20409
|
style: {
|
|
@@ -20063,12 +20419,12 @@ function VideoUrlInput({ value, onCommit }) {
|
|
|
20063
20419
|
boxShadow: invalid ? "inset 0 0 0 1.5px #EF4444" : "none"
|
|
20064
20420
|
},
|
|
20065
20421
|
children: [
|
|
20066
|
-
/* @__PURE__ */ (0,
|
|
20422
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
|
|
20067
20423
|
"span",
|
|
20068
20424
|
{
|
|
20069
20425
|
style: {
|
|
20070
20426
|
flex: "0 0 auto",
|
|
20071
|
-
color:
|
|
20427
|
+
color: OHW_BLUE_DARK,
|
|
20072
20428
|
fontSize: 10,
|
|
20073
20429
|
lineHeight: "16px",
|
|
20074
20430
|
fontWeight: 700,
|
|
@@ -20078,14 +20434,14 @@ function VideoUrlInput({ value, onCommit }) {
|
|
|
20078
20434
|
children: "Video"
|
|
20079
20435
|
}
|
|
20080
20436
|
),
|
|
20081
|
-
/* @__PURE__ */ (0,
|
|
20437
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
|
|
20082
20438
|
"input",
|
|
20083
20439
|
{
|
|
20084
20440
|
type: "text",
|
|
20085
20441
|
inputMode: "url",
|
|
20086
20442
|
value: draft,
|
|
20087
20443
|
onChange: (e) => handleChange(e.target.value),
|
|
20088
|
-
onBlur:
|
|
20444
|
+
onBlur: commit2,
|
|
20089
20445
|
onKeyDown: (e) => {
|
|
20090
20446
|
if (e.key === "Enter") e.currentTarget.blur();
|
|
20091
20447
|
if (e.key === "Escape") {
|
|
@@ -20115,7 +20471,7 @@ function VideoUrlInput({ value, onCommit }) {
|
|
|
20115
20471
|
]
|
|
20116
20472
|
}
|
|
20117
20473
|
),
|
|
20118
|
-
invalid && /* @__PURE__ */ (0,
|
|
20474
|
+
invalid && /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("div", { style: { color: "#FCA5A5", fontSize: 11, textAlign: "center" }, children: "That doesn't look like a YouTube link \u2014 try pasting the video URL again." })
|
|
20119
20475
|
] });
|
|
20120
20476
|
}
|
|
20121
20477
|
function VideoToolbar({
|
|
@@ -20125,7 +20481,7 @@ function VideoToolbar({
|
|
|
20125
20481
|
onSetVideoId,
|
|
20126
20482
|
onRemove
|
|
20127
20483
|
}) {
|
|
20128
|
-
return /* @__PURE__ */ (0,
|
|
20484
|
+
return /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)(
|
|
20129
20485
|
"div",
|
|
20130
20486
|
{
|
|
20131
20487
|
"data-ohw-bridge": "",
|
|
@@ -20137,7 +20493,7 @@ function VideoToolbar({
|
|
|
20137
20493
|
gap: 6,
|
|
20138
20494
|
alignItems: "center",
|
|
20139
20495
|
width: 280,
|
|
20140
|
-
background:
|
|
20496
|
+
background: OHW_BLUE,
|
|
20141
20497
|
padding: 8,
|
|
20142
20498
|
borderRadius: 12,
|
|
20143
20499
|
boxShadow: "0 8px 24px rgba(0,0,0,0.25)",
|
|
@@ -20145,9 +20501,9 @@ function VideoToolbar({
|
|
|
20145
20501
|
opacity: pending ? 0.6 : 1
|
|
20146
20502
|
},
|
|
20147
20503
|
children: [
|
|
20148
|
-
/* @__PURE__ */ (0,
|
|
20149
|
-
/* @__PURE__ */ (0,
|
|
20150
|
-
error && /* @__PURE__ */ (0,
|
|
20504
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)(VideoUrlInput, { value: videoId, onCommit: onSetVideoId }),
|
|
20505
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)(Pill, { label: "Remove video", onClick: onRemove, disabled: !videoId }),
|
|
20506
|
+
error && /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("div", { style: { color: "#FCA5A5", fontSize: 11, maxWidth: 220, textAlign: "center" }, children: error })
|
|
20151
20507
|
]
|
|
20152
20508
|
}
|
|
20153
20509
|
);
|
|
@@ -20267,8 +20623,8 @@ function AiVideoOverlay({
|
|
|
20267
20623
|
const activeBlockRect = useLiveBlockRect(active);
|
|
20268
20624
|
const TOOLBAR_APPROX_H = 90;
|
|
20269
20625
|
const toolbarState = activeBlockRect && activeBlockRect.top < TOOLBAR_APPROX_H ? "active-bottom" : "active-top";
|
|
20270
|
-
return /* @__PURE__ */ (0,
|
|
20271
|
-
hoverHandleRect && hover && /* @__PURE__ */ (0,
|
|
20626
|
+
return /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)(import_jsx_runtime23.Fragment, { children: [
|
|
20627
|
+
hoverHandleRect && hover && /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
|
|
20272
20628
|
"button",
|
|
20273
20629
|
{
|
|
20274
20630
|
type: "button",
|
|
@@ -20296,15 +20652,15 @@ function AiVideoOverlay({
|
|
|
20296
20652
|
fontSize: 14,
|
|
20297
20653
|
fontWeight: 700
|
|
20298
20654
|
},
|
|
20299
|
-
children: /* @__PURE__ */ (0,
|
|
20655
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(import_lucide_react11.Star, { size: 14, style: { pointerEvents: "none" } })
|
|
20300
20656
|
}
|
|
20301
20657
|
),
|
|
20302
|
-
activeBlockRect && active && activeEntry && /* @__PURE__ */ (0,
|
|
20658
|
+
activeBlockRect && active && activeEntry && /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
|
|
20303
20659
|
ItemInteractionLayer,
|
|
20304
20660
|
{
|
|
20305
20661
|
rect: activeBlockRect,
|
|
20306
20662
|
state: toolbarState,
|
|
20307
|
-
toolbar: /* @__PURE__ */ (0,
|
|
20663
|
+
toolbar: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
|
|
20308
20664
|
VideoToolbar,
|
|
20309
20665
|
{
|
|
20310
20666
|
videoId: videoIdAt(activeEntry.tree, active.path),
|
|
@@ -20328,7 +20684,7 @@ function AiVideoOverlay({
|
|
|
20328
20684
|
|
|
20329
20685
|
// src/ui/ai-section/AiFadeCarouselOverlay.tsx
|
|
20330
20686
|
var import_react13 = require("react");
|
|
20331
|
-
var
|
|
20687
|
+
var import_lucide_react12 = require("lucide-react");
|
|
20332
20688
|
|
|
20333
20689
|
// src/lib/ai-carousel-tree.ts
|
|
20334
20690
|
function isCarouselBlock(node) {
|
|
@@ -20379,10 +20735,10 @@ function setCarouselAutoplay(tree, on) {
|
|
|
20379
20735
|
}
|
|
20380
20736
|
|
|
20381
20737
|
// src/ui/ai-section/AiFadeCarouselOverlay.tsx
|
|
20382
|
-
var
|
|
20738
|
+
var import_jsx_runtime24 = require("react/jsx-runtime");
|
|
20383
20739
|
var PRIMARY6 = "#0885FE";
|
|
20384
|
-
var
|
|
20385
|
-
var
|
|
20740
|
+
var OHW_BLUE2 = `var(--ohw-primary, ${PRIMARY6})`;
|
|
20741
|
+
var OHW_BLUE_DARK2 = `color-mix(in srgb, var(--ohw-primary, ${PRIMARY6}) 60%, #000000)`;
|
|
20386
20742
|
function findCarouselItemElement(sectionId, index) {
|
|
20387
20743
|
const sectionEl = findByInstanceId(sectionId);
|
|
20388
20744
|
if (!sectionEl) return null;
|
|
@@ -20461,8 +20817,8 @@ function requestAssetPick2(postToParent2) {
|
|
|
20461
20817
|
postToParent2({ type: "ow:asset-pick", id });
|
|
20462
20818
|
});
|
|
20463
20819
|
}
|
|
20464
|
-
function
|
|
20465
|
-
return /* @__PURE__ */ (0,
|
|
20820
|
+
function Pill2({ label, onClick, disabled }) {
|
|
20821
|
+
return /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
|
|
20466
20822
|
"button",
|
|
20467
20823
|
{
|
|
20468
20824
|
type: "button",
|
|
@@ -20478,7 +20834,7 @@ function Pill3({ label, onClick, disabled }) {
|
|
|
20478
20834
|
border: "none",
|
|
20479
20835
|
cursor: disabled ? "default" : "pointer",
|
|
20480
20836
|
background: "#ffffff",
|
|
20481
|
-
color:
|
|
20837
|
+
color: OHW_BLUE_DARK2,
|
|
20482
20838
|
opacity: disabled ? 0.4 : 1,
|
|
20483
20839
|
fontSize: 12,
|
|
20484
20840
|
lineHeight: "16px",
|
|
@@ -20496,7 +20852,7 @@ function TogglePill({
|
|
|
20496
20852
|
onToggle,
|
|
20497
20853
|
disabled
|
|
20498
20854
|
}) {
|
|
20499
|
-
return /* @__PURE__ */ (0,
|
|
20855
|
+
return /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(
|
|
20500
20856
|
"button",
|
|
20501
20857
|
{
|
|
20502
20858
|
type: "button",
|
|
@@ -20515,7 +20871,7 @@ function TogglePill({
|
|
|
20515
20871
|
border: "none",
|
|
20516
20872
|
cursor: disabled ? "default" : "pointer",
|
|
20517
20873
|
background: "#ffffff",
|
|
20518
|
-
color:
|
|
20874
|
+
color: OHW_BLUE_DARK2,
|
|
20519
20875
|
opacity: disabled ? 0.4 : 1,
|
|
20520
20876
|
fontSize: 12,
|
|
20521
20877
|
lineHeight: "16px",
|
|
@@ -20525,7 +20881,7 @@ function TogglePill({
|
|
|
20525
20881
|
},
|
|
20526
20882
|
children: [
|
|
20527
20883
|
label,
|
|
20528
|
-
/* @__PURE__ */ (0,
|
|
20884
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
|
|
20529
20885
|
"span",
|
|
20530
20886
|
{
|
|
20531
20887
|
"aria-hidden": true,
|
|
@@ -20538,10 +20894,10 @@ function TogglePill({
|
|
|
20538
20894
|
// Off is a grey track, not a washed-out blue: the pill's own white background already
|
|
20539
20895
|
// carries the brand colour in the text, and a pale blue track next to it read as
|
|
20540
20896
|
// "disabled control" rather than "switch that is off".
|
|
20541
|
-
background: on ?
|
|
20897
|
+
background: on ? OHW_BLUE_DARK2 : "#CBD5E1",
|
|
20542
20898
|
transition: "background 120ms ease"
|
|
20543
20899
|
},
|
|
20544
|
-
children: /* @__PURE__ */ (0,
|
|
20900
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
|
|
20545
20901
|
"span",
|
|
20546
20902
|
{
|
|
20547
20903
|
style: {
|
|
@@ -20570,7 +20926,7 @@ function CarouselSlideToolbar({
|
|
|
20570
20926
|
onChangeImage,
|
|
20571
20927
|
onToggleAutoplay
|
|
20572
20928
|
}) {
|
|
20573
|
-
return /* @__PURE__ */ (0,
|
|
20929
|
+
return /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(
|
|
20574
20930
|
"div",
|
|
20575
20931
|
{
|
|
20576
20932
|
"data-ohw-bridge": "",
|
|
@@ -20581,7 +20937,7 @@ function CarouselSlideToolbar({
|
|
|
20581
20937
|
flexDirection: "column",
|
|
20582
20938
|
gap: 6,
|
|
20583
20939
|
alignItems: "center",
|
|
20584
|
-
background:
|
|
20940
|
+
background: OHW_BLUE2,
|
|
20585
20941
|
padding: 8,
|
|
20586
20942
|
borderRadius: 12,
|
|
20587
20943
|
boxShadow: "0 8px 24px rgba(0,0,0,0.25)",
|
|
@@ -20593,11 +20949,11 @@ function CarouselSlideToolbar({
|
|
|
20593
20949
|
pointerEvents: pending ? "none" : "auto"
|
|
20594
20950
|
},
|
|
20595
20951
|
children: [
|
|
20596
|
-
/* @__PURE__ */ (0,
|
|
20597
|
-
/* @__PURE__ */ (0,
|
|
20598
|
-
/* @__PURE__ */ (0,
|
|
20952
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { style: { display: "flex", gap: 6, alignItems: "center" }, children: [
|
|
20953
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)(Pill2, { label: "Change Image", onClick: onChangeImage }),
|
|
20954
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)(TogglePill, { label: "Autoplay", on: autoplay, onToggle: onToggleAutoplay })
|
|
20599
20955
|
] }),
|
|
20600
|
-
error && /* @__PURE__ */ (0,
|
|
20956
|
+
error && /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("div", { style: { color: "#FCA5A5", fontSize: 11, maxWidth: 220, textAlign: "center" }, children: error })
|
|
20601
20957
|
]
|
|
20602
20958
|
}
|
|
20603
20959
|
);
|
|
@@ -20737,8 +21093,8 @@ function AiFadeCarouselOverlay({
|
|
|
20737
21093
|
const activeItemRect = useLiveItemRect2(active);
|
|
20738
21094
|
const TOOLBAR_APPROX_H = 90;
|
|
20739
21095
|
const toolbarState = activeItemRect && activeItemRect.top < TOOLBAR_APPROX_H ? "active-bottom" : "active-top";
|
|
20740
|
-
return /* @__PURE__ */ (0,
|
|
20741
|
-
hoverHandleRect && hover && /* @__PURE__ */ (0,
|
|
21096
|
+
return /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(import_jsx_runtime24.Fragment, { children: [
|
|
21097
|
+
hoverHandleRect && hover && /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
|
|
20742
21098
|
"button",
|
|
20743
21099
|
{
|
|
20744
21100
|
type: "button",
|
|
@@ -20767,10 +21123,10 @@ function AiFadeCarouselOverlay({
|
|
|
20767
21123
|
fontSize: 14,
|
|
20768
21124
|
fontWeight: 700
|
|
20769
21125
|
},
|
|
20770
|
-
children: /* @__PURE__ */ (0,
|
|
21126
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(import_lucide_react12.Star, { size: 14, style: { pointerEvents: "none" } })
|
|
20771
21127
|
}
|
|
20772
21128
|
),
|
|
20773
|
-
swapping && /* @__PURE__ */ (0,
|
|
21129
|
+
swapping && /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
|
|
20774
21130
|
"div",
|
|
20775
21131
|
{
|
|
20776
21132
|
ref: skeletonRef,
|
|
@@ -20788,15 +21144,15 @@ function AiFadeCarouselOverlay({
|
|
|
20788
21144
|
zIndex: 2147483646,
|
|
20789
21145
|
pointerEvents: "none"
|
|
20790
21146
|
},
|
|
20791
|
-
children: /* @__PURE__ */ (0,
|
|
21147
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("style", { children: MEDIA_SKELETON_CSS })
|
|
20792
21148
|
}
|
|
20793
21149
|
),
|
|
20794
|
-
activeItemRect && active && activeEntry && /* @__PURE__ */ (0,
|
|
21150
|
+
activeItemRect && active && activeEntry && /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
|
|
20795
21151
|
ItemInteractionLayer,
|
|
20796
21152
|
{
|
|
20797
21153
|
rect: activeItemRect,
|
|
20798
21154
|
state: toolbarState,
|
|
20799
|
-
toolbar: /* @__PURE__ */ (0,
|
|
21155
|
+
toolbar: /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
|
|
20800
21156
|
CarouselSlideToolbar,
|
|
20801
21157
|
{
|
|
20802
21158
|
pending,
|
|
@@ -21014,113 +21370,6 @@ function scrollToHashSectionWhenReady(behavior = "smooth") {
|
|
|
21014
21370
|
// src/ui/link-modal/LinkPopover.tsx
|
|
21015
21371
|
var import_react17 = require("react");
|
|
21016
21372
|
|
|
21017
|
-
// src/ui/dialog.tsx
|
|
21018
|
-
var React9 = __toESM(require("react"), 1);
|
|
21019
|
-
var import_radix_ui6 = require("radix-ui");
|
|
21020
|
-
var import_lucide_react12 = require("lucide-react");
|
|
21021
|
-
var import_jsx_runtime24 = require("react/jsx-runtime");
|
|
21022
|
-
function Dialog2({
|
|
21023
|
-
...props
|
|
21024
|
-
}) {
|
|
21025
|
-
return /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(import_radix_ui6.Dialog.Root, { "data-slot": "dialog", ...props });
|
|
21026
|
-
}
|
|
21027
|
-
function DialogPortal({
|
|
21028
|
-
...props
|
|
21029
|
-
}) {
|
|
21030
|
-
return /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(import_radix_ui6.Dialog.Portal, { ...props });
|
|
21031
|
-
}
|
|
21032
|
-
function DialogOverlay({
|
|
21033
|
-
className,
|
|
21034
|
-
...props
|
|
21035
|
-
}) {
|
|
21036
|
-
return /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
|
|
21037
|
-
import_radix_ui6.Dialog.Overlay,
|
|
21038
|
-
{
|
|
21039
|
-
"data-slot": "dialog-overlay",
|
|
21040
|
-
"data-ohw-link-modal-root": "",
|
|
21041
|
-
className: cn("fixed inset-0 z-[2147483646] bg-black/50", className),
|
|
21042
|
-
...props
|
|
21043
|
-
}
|
|
21044
|
-
);
|
|
21045
|
-
}
|
|
21046
|
-
var DialogContent = React9.forwardRef(
|
|
21047
|
-
({ className, children, showCloseButton = true, container, ...props }, ref) => {
|
|
21048
|
-
const positionMode = container ? "absolute" : "fixed";
|
|
21049
|
-
return /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(DialogPortal, { container: container ?? void 0, children: [
|
|
21050
|
-
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)(DialogOverlay, { className: cn(positionMode, "inset-0") }),
|
|
21051
|
-
/* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(
|
|
21052
|
-
import_radix_ui6.Dialog.Content,
|
|
21053
|
-
{
|
|
21054
|
-
ref,
|
|
21055
|
-
"data-slot": "dialog-content",
|
|
21056
|
-
className: cn(
|
|
21057
|
-
positionMode,
|
|
21058
|
-
"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",
|
|
21059
|
-
"rounded-xl border border-border bg-background font-sans shadow-lg outline-none",
|
|
21060
|
-
container ? "max-h-[calc(100%-32px)]" : "max-h-[calc(100vh-32px)]",
|
|
21061
|
-
className
|
|
21062
|
-
),
|
|
21063
|
-
onMouseDown: (e) => e.stopPropagation(),
|
|
21064
|
-
...props,
|
|
21065
|
-
children: [
|
|
21066
|
-
children,
|
|
21067
|
-
showCloseButton ? /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
|
|
21068
|
-
import_radix_ui6.Dialog.Close,
|
|
21069
|
-
{
|
|
21070
|
-
type: "button",
|
|
21071
|
-
className: "absolute right-[9px] top-[9px] rounded-sm p-1.5 text-foreground hover:bg-muted/50",
|
|
21072
|
-
"aria-label": "Close",
|
|
21073
|
-
children: /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(import_lucide_react12.X, { size: 16, "aria-hidden": true })
|
|
21074
|
-
}
|
|
21075
|
-
) : null
|
|
21076
|
-
]
|
|
21077
|
-
}
|
|
21078
|
-
)
|
|
21079
|
-
] });
|
|
21080
|
-
}
|
|
21081
|
-
);
|
|
21082
|
-
DialogContent.displayName = import_radix_ui6.Dialog.Content.displayName;
|
|
21083
|
-
function DialogHeader({
|
|
21084
|
-
className,
|
|
21085
|
-
...props
|
|
21086
|
-
}) {
|
|
21087
|
-
return /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("div", { className: cn("flex flex-col gap-1.5", className), ...props });
|
|
21088
|
-
}
|
|
21089
|
-
function DialogFooter({
|
|
21090
|
-
className,
|
|
21091
|
-
...props
|
|
21092
|
-
}) {
|
|
21093
|
-
return /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
|
|
21094
|
-
"div",
|
|
21095
|
-
{
|
|
21096
|
-
className: cn("flex items-center justify-end gap-2", className),
|
|
21097
|
-
...props
|
|
21098
|
-
}
|
|
21099
|
-
);
|
|
21100
|
-
}
|
|
21101
|
-
var DialogTitle = React9.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
|
|
21102
|
-
import_radix_ui6.Dialog.Title,
|
|
21103
|
-
{
|
|
21104
|
-
ref,
|
|
21105
|
-
className: cn(
|
|
21106
|
-
"text-lg font-semibold leading-none tracking-tight text-card-foreground",
|
|
21107
|
-
className
|
|
21108
|
-
),
|
|
21109
|
-
...props
|
|
21110
|
-
}
|
|
21111
|
-
));
|
|
21112
|
-
DialogTitle.displayName = import_radix_ui6.Dialog.Title.displayName;
|
|
21113
|
-
var DialogDescription = React9.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
|
|
21114
|
-
import_radix_ui6.Dialog.Description,
|
|
21115
|
-
{
|
|
21116
|
-
ref,
|
|
21117
|
-
className: cn("text-sm text-muted-foreground", className),
|
|
21118
|
-
...props
|
|
21119
|
-
}
|
|
21120
|
-
));
|
|
21121
|
-
DialogDescription.displayName = import_radix_ui6.Dialog.Description.displayName;
|
|
21122
|
-
var DialogClose = import_radix_ui6.Dialog.Close;
|
|
21123
|
-
|
|
21124
21373
|
// src/ui/link-modal/LinkEditorPanel.tsx
|
|
21125
21374
|
var import_lucide_react16 = require("lucide-react");
|
|
21126
21375
|
|
|
@@ -22224,6 +22473,7 @@ function shouldUseDevFixtures() {
|
|
|
22224
22473
|
function getLogoElement(el) {
|
|
22225
22474
|
const marked = el.closest('[data-ohw-role="logo"], [data-ohw-logo]');
|
|
22226
22475
|
if (marked) return marked;
|
|
22476
|
+
if (el.closest('[data-ohw-editable="icon"]')) return null;
|
|
22227
22477
|
const root = el.closest("nav, [data-ohw-nav-root], footer");
|
|
22228
22478
|
if (!root) return null;
|
|
22229
22479
|
const anchor = el.closest("a");
|
|
@@ -23918,6 +24168,102 @@ function deleteSelectedNavFooterItem(deps) {
|
|
|
23918
24168
|
return false;
|
|
23919
24169
|
}
|
|
23920
24170
|
|
|
24171
|
+
// src/lib/nav-page-sync.ts
|
|
24172
|
+
function labelKeyFor(hrefKey) {
|
|
24173
|
+
return hrefKey.replace(/-href$/, "-label");
|
|
24174
|
+
}
|
|
24175
|
+
function isPageLinkKey(key) {
|
|
24176
|
+
return isNavbarHrefKey(key) || isFooterHrefKey(key);
|
|
24177
|
+
}
|
|
24178
|
+
function currentHref(key, anchor, content) {
|
|
24179
|
+
const stored = content[key];
|
|
24180
|
+
if (typeof stored === "string" && stored.length > 0) return stored;
|
|
24181
|
+
return anchor.getAttribute("href") ?? "";
|
|
24182
|
+
}
|
|
24183
|
+
function normalizePath2(value) {
|
|
24184
|
+
if (value.length > 1 && value.endsWith("/")) return value.slice(0, -1);
|
|
24185
|
+
return value;
|
|
24186
|
+
}
|
|
24187
|
+
function pointsAt(href, path) {
|
|
24188
|
+
const normalized = normalizePath2(href);
|
|
24189
|
+
const target = normalizePath2(path);
|
|
24190
|
+
if (normalized === target) return true;
|
|
24191
|
+
return (normalized.startsWith(`${target}#`) || normalized.startsWith(`${target}?`)) && target !== "/";
|
|
24192
|
+
}
|
|
24193
|
+
function retargetHref(href, oldPath, newPath) {
|
|
24194
|
+
const normalized = normalizePath2(href);
|
|
24195
|
+
const target = normalizePath2(oldPath);
|
|
24196
|
+
if (normalized === target) return newPath;
|
|
24197
|
+
return `${newPath}${normalized.slice(target.length)}`;
|
|
24198
|
+
}
|
|
24199
|
+
function setLabelText(key, text) {
|
|
24200
|
+
document.querySelectorAll(`[data-ohw-key="${CSS.escape(key)}"]`).forEach((el) => {
|
|
24201
|
+
el.textContent = text;
|
|
24202
|
+
});
|
|
24203
|
+
}
|
|
24204
|
+
function commit(delta, deps) {
|
|
24205
|
+
if (Object.keys(delta).length === 0) return;
|
|
24206
|
+
deps.setEditContent({ ...deps.getEditContent(), ...delta });
|
|
24207
|
+
deps.postToParent({
|
|
24208
|
+
type: "ow:change",
|
|
24209
|
+
nodes: Object.entries(delta).map(([key, text]) => ({ key, text }))
|
|
24210
|
+
});
|
|
24211
|
+
}
|
|
24212
|
+
function navLinksTo(path, content) {
|
|
24213
|
+
return Array.from(document.querySelectorAll("[data-ohw-href-key]")).filter((anchor) => {
|
|
24214
|
+
const key = anchor.getAttribute("data-ohw-href-key");
|
|
24215
|
+
return isNavbarHrefKey(key) && pointsAt(currentHref(key, anchor, content), path);
|
|
24216
|
+
}).map((anchor) => anchor.getAttribute("data-ohw-href-key"));
|
|
24217
|
+
}
|
|
24218
|
+
function addNavLinkForPage(page, deps) {
|
|
24219
|
+
const content = deps.getEditContent();
|
|
24220
|
+
if (navLinksTo(page.path, content).length > 0) return false;
|
|
24221
|
+
const roots = listNavbarRootItems();
|
|
24222
|
+
const afterAnchor = roots[roots.length - 1] ?? null;
|
|
24223
|
+
let inserted;
|
|
24224
|
+
try {
|
|
24225
|
+
inserted = insertNavbarItem(page.path, page.title, afterAnchor);
|
|
24226
|
+
} catch {
|
|
24227
|
+
return false;
|
|
24228
|
+
}
|
|
24229
|
+
const { hrefKey, labelKey, index } = inserted;
|
|
24230
|
+
deps.applyLinkByKey(hrefKey, page.path);
|
|
24231
|
+
setLabelText(labelKey, page.title);
|
|
24232
|
+
commit(
|
|
24233
|
+
{
|
|
24234
|
+
[hrefKey]: page.path,
|
|
24235
|
+
[labelKey]: page.title,
|
|
24236
|
+
[NAV_COUNT_KEY]: String(index + 1),
|
|
24237
|
+
[NAV_ORDER_KEY]: getNavbarOrderJson()
|
|
24238
|
+
},
|
|
24239
|
+
deps
|
|
24240
|
+
);
|
|
24241
|
+
return true;
|
|
24242
|
+
}
|
|
24243
|
+
function retargetPageLinks(change, deps) {
|
|
24244
|
+
const { oldPath, newPath, oldTitle, newTitle } = change;
|
|
24245
|
+
if (!oldPath || !newPath || normalizePath2(oldPath) === normalizePath2(newPath)) return 0;
|
|
24246
|
+
const content = deps.getEditContent();
|
|
24247
|
+
const delta = {};
|
|
24248
|
+
for (const anchor of Array.from(document.querySelectorAll("[data-ohw-href-key]"))) {
|
|
24249
|
+
const hrefKey = anchor.getAttribute("data-ohw-href-key");
|
|
24250
|
+
if (!isPageLinkKey(hrefKey)) continue;
|
|
24251
|
+
const href = currentHref(hrefKey, anchor, content);
|
|
24252
|
+
if (!pointsAt(href, oldPath)) continue;
|
|
24253
|
+
const nextHref = retargetHref(href, oldPath, newPath);
|
|
24254
|
+
deps.applyLinkByKey(hrefKey, nextHref);
|
|
24255
|
+
delta[hrefKey] = nextHref;
|
|
24256
|
+
if (!oldTitle || !newTitle) continue;
|
|
24257
|
+
const labelKey = labelKeyFor(hrefKey);
|
|
24258
|
+
const label = content[labelKey] ?? anchor.querySelector('[data-ohw-editable="text"]')?.textContent ?? "";
|
|
24259
|
+
if (label.trim() !== oldTitle) continue;
|
|
24260
|
+
setLabelText(labelKey, newTitle);
|
|
24261
|
+
delta[labelKey] = newTitle;
|
|
24262
|
+
}
|
|
24263
|
+
commit(delta, deps);
|
|
24264
|
+
return Object.keys(delta).filter((key) => key.endsWith("-href")).length;
|
|
24265
|
+
}
|
|
24266
|
+
|
|
23921
24267
|
// src/ui/navbar-container-chrome.tsx
|
|
23922
24268
|
var import_lucide_react21 = require("lucide-react");
|
|
23923
24269
|
var import_jsx_runtime37 = require("react/jsx-runtime");
|
|
@@ -24805,7 +25151,7 @@ function getNavigationSelectionParent(el) {
|
|
|
24805
25151
|
if (!isFooterLinksContainer(el) && (el.hasAttribute("data-ohw-footer-col") || el.hasAttribute("data-ohw-footer-column") || isInferredFooterGroup2(el))) {
|
|
24806
25152
|
return resolveFooterLinksContainerFrom(el);
|
|
24807
25153
|
}
|
|
24808
|
-
if (el.hasAttribute("data-ohw-nav-container") || el.hasAttribute("data-ohw-nav-drawer") || isFooterLinksContainer(el)) {
|
|
25154
|
+
if (el.hasAttribute("data-ohw-nav-container") || el.hasAttribute("data-ohw-nav-drawer") || el.hasAttribute("data-ohw-footer-col") || el.hasAttribute("data-ohw-footer-column") || isFooterLinksContainer(el) || isInferredFooterGroup2(el)) {
|
|
24809
25155
|
return getNavigationRoot(el);
|
|
24810
25156
|
}
|
|
24811
25157
|
return null;
|
|
@@ -25027,7 +25373,6 @@ var ICONS = {
|
|
|
25027
25373
|
insertUnorderedList: '<line x1="8" y1="6" x2="21" y2="6"/><line x1="8" y1="12" x2="21" y2="12"/><line x1="8" y1="18" x2="21" y2="18"/><line x1="3" y1="6" x2="3.01" y2="6"/><line x1="3" y1="12" x2="3.01" y2="12"/><line x1="3" y1="18" x2="3.01" y2="18"/>',
|
|
25028
25374
|
insertOrderedList: '<line x1="10" y1="6" x2="21" y2="6"/><line x1="10" y1="12" x2="21" y2="12"/><line x1="10" y1="18" x2="21" y2="18"/><path d="M4 6h1v4"/><path d="M4 10h2"/><path d="M6 18H4c0-1 2-2 2-3s-1-1.5-2-1"/>'
|
|
25029
25375
|
};
|
|
25030
|
-
var HEIGHT_SETTLE_DELAYS = [150, 400, 800];
|
|
25031
25376
|
var SELECTION_CHROME_GAP2 = 4;
|
|
25032
25377
|
var TOOLBAR_STROKE_GAP2 = 4;
|
|
25033
25378
|
var TOOLBAR_OFFSET_FROM_ELEMENT = SELECTION_CHROME_GAP2 + TOOLBAR_STROKE_GAP2;
|
|
@@ -25125,7 +25470,7 @@ function applyVisibleViewport(el, parentScroll) {
|
|
|
25125
25470
|
el.style.top = `${top}px`;
|
|
25126
25471
|
el.style.height = `${height}px`;
|
|
25127
25472
|
}
|
|
25128
|
-
var
|
|
25473
|
+
var TOOLBAR_EDGE_MARGIN4 = 4;
|
|
25129
25474
|
function clampToolbarToClip(top, transform, rect, clip, approxH, gap) {
|
|
25130
25475
|
const isAbove = transform.includes("translateY(-100%)");
|
|
25131
25476
|
let visualTop = isAbove ? top - approxH : top;
|
|
@@ -25152,8 +25497,8 @@ function clampToolbarToClip(top, transform, rect, clip, approxH, gap) {
|
|
|
25152
25497
|
function clampToolbarLeft(centerX, toolbarWidth) {
|
|
25153
25498
|
const half = toolbarWidth / 2;
|
|
25154
25499
|
return Math.max(
|
|
25155
|
-
|
|
25156
|
-
Math.min(centerX, window.innerWidth -
|
|
25500
|
+
TOOLBAR_EDGE_MARGIN4 + half,
|
|
25501
|
+
Math.min(centerX, window.innerWidth - TOOLBAR_EDGE_MARGIN4 - half)
|
|
25157
25502
|
);
|
|
25158
25503
|
}
|
|
25159
25504
|
function calcToolbarPos(rect, parentScroll, toolbarW = 306) {
|
|
@@ -26033,21 +26378,6 @@ function OhhwellsBridge() {
|
|
|
26033
26378
|
const [isItemDragging, setIsItemDragging] = (0, import_react21.useState)(false);
|
|
26034
26379
|
const [isFooterFrameSelection, setIsFooterFrameSelection] = (0, import_react21.useState)(false);
|
|
26035
26380
|
isFooterFrameSelectionRef.current = isFooterFrameSelection;
|
|
26036
|
-
const [floatingPanel, setFloatingPanel] = (0, import_react21.useState)(null);
|
|
26037
|
-
const floatingPanelOpenRef = (0, import_react21.useRef)(false);
|
|
26038
|
-
floatingPanelOpenRef.current = floatingPanel !== null;
|
|
26039
|
-
const floatingPanelRef = (0, import_react21.useRef)(null);
|
|
26040
|
-
floatingPanelRef.current = floatingPanel;
|
|
26041
|
-
const [floatingPanelPos, setFloatingPanelPos] = (0, import_react21.useState)(null);
|
|
26042
|
-
const buttonCollectionDragRef = (0, import_react21.useRef)(null);
|
|
26043
|
-
const buttonDropInsertIndexRef = (0, import_react21.useRef)(null);
|
|
26044
|
-
const [buttonDropSlots, setButtonDropSlots] = (0, import_react21.useState)([]);
|
|
26045
|
-
const [activeButtonDropIndex, setActiveButtonDropIndex] = (0, import_react21.useState)(null);
|
|
26046
|
-
const buttonPointerDragRef = (0, import_react21.useRef)(null);
|
|
26047
|
-
const [buttonStyleTick, setButtonStyleTick] = (0, import_react21.useState)(0);
|
|
26048
|
-
const [logoSizeDraft, setLogoSizeDraft] = (0, import_react21.useState)(null);
|
|
26049
|
-
const [editorViewport, setEditorViewport] = (0, import_react21.useState)("desktop");
|
|
26050
|
-
const [parentScrollSnap, setParentScrollSnap] = (0, import_react21.useState)(null);
|
|
26051
26381
|
const [navDropdownPreviewOpen, setNavDropdownPreviewOpen] = (0, import_react21.useState)(null);
|
|
26052
26382
|
const [footerHeadingVisible, setFooterHeadingVisible] = (0, import_react21.useState)(null);
|
|
26053
26383
|
const footerDragRef = (0, import_react21.useRef)(null);
|
|
@@ -26073,6 +26403,21 @@ function OhhwellsBridge() {
|
|
|
26073
26403
|
const stylesRef = (0, import_react21.useRef)("");
|
|
26074
26404
|
const appliedDrawerRef = (0, import_react21.useRef)(null);
|
|
26075
26405
|
const pendingDeleteUndoRef = (0, import_react21.useRef)(null);
|
|
26406
|
+
const [floatingPanel, setFloatingPanel] = (0, import_react21.useState)(null);
|
|
26407
|
+
const floatingPanelOpenRef = (0, import_react21.useRef)(false);
|
|
26408
|
+
const floatingPanelRef = (0, import_react21.useRef)(null);
|
|
26409
|
+
floatingPanelRef.current = floatingPanel;
|
|
26410
|
+
const setFloatingPanelRef = (0, import_react21.useRef)(setFloatingPanel);
|
|
26411
|
+
const [floatingPanelPos, setFloatingPanelPos] = (0, import_react21.useState)(null);
|
|
26412
|
+
const buttonCollectionDragRef = (0, import_react21.useRef)(null);
|
|
26413
|
+
const buttonDropInsertIndexRef = (0, import_react21.useRef)(null);
|
|
26414
|
+
const [buttonDropSlots, setButtonDropSlots] = (0, import_react21.useState)([]);
|
|
26415
|
+
const [activeButtonDropIndex, setActiveButtonDropIndex] = (0, import_react21.useState)(null);
|
|
26416
|
+
const buttonPointerDragRef = (0, import_react21.useRef)(null);
|
|
26417
|
+
const [buttonStyleTick, setButtonStyleTick] = (0, import_react21.useState)(0);
|
|
26418
|
+
const [logoSizeDraft, setLogoSizeDraft] = (0, import_react21.useState)(null);
|
|
26419
|
+
const [editorViewport, setEditorViewport] = (0, import_react21.useState)("desktop");
|
|
26420
|
+
const [parentScrollSnap, setParentScrollSnap] = (0, import_react21.useState)(null);
|
|
26076
26421
|
const [sitePages, setSitePages] = (0, import_react21.useState)([]);
|
|
26077
26422
|
const collectionItemsRef = (0, import_react21.useRef)(/* @__PURE__ */ new Map());
|
|
26078
26423
|
const [sectionsByPath, setSectionsByPath] = (0, import_react21.useState)({});
|
|
@@ -26082,7 +26427,18 @@ function OhhwellsBridge() {
|
|
|
26082
26427
|
const linkPopoverOpenRef = (0, import_react21.useRef)(false);
|
|
26083
26428
|
const linkPopoverGraceUntilRef = (0, import_react21.useRef)(0);
|
|
26084
26429
|
setLinkPopoverRef.current = setLinkPopover;
|
|
26430
|
+
setFloatingPanelRef.current = setFloatingPanel;
|
|
26085
26431
|
linkPopoverSessionRef.current = linkPopover;
|
|
26432
|
+
floatingPanelOpenRef.current = Boolean(floatingPanel);
|
|
26433
|
+
(0, import_react21.useEffect)(() => {
|
|
26434
|
+
const syncViewport = () => {
|
|
26435
|
+
const next = window.innerWidth <= 480 ? "mobile" : "desktop";
|
|
26436
|
+
setEditorViewport((prev) => prev === next ? prev : next);
|
|
26437
|
+
};
|
|
26438
|
+
syncViewport();
|
|
26439
|
+
window.addEventListener("resize", syncViewport);
|
|
26440
|
+
return () => window.removeEventListener("resize", syncViewport);
|
|
26441
|
+
}, []);
|
|
26086
26442
|
(0, import_react21.useEffect)(() => {
|
|
26087
26443
|
setSectionOrderPersistHandler((entries) => {
|
|
26088
26444
|
const currentPath = window.location.pathname;
|
|
@@ -26231,6 +26587,43 @@ function OhhwellsBridge() {
|
|
|
26231
26587
|
if (!useFixtures) postToParent2({ type: "ow:request-site-pages" });
|
|
26232
26588
|
return () => window.removeEventListener("message", onSitePages);
|
|
26233
26589
|
}, [isEditMode, postToParent2]);
|
|
26590
|
+
(0, import_react21.useEffect)(() => {
|
|
26591
|
+
if (!isEditMode) return;
|
|
26592
|
+
const deps = {
|
|
26593
|
+
getEditContent: () => editContentRef.current,
|
|
26594
|
+
setEditContent: (next) => {
|
|
26595
|
+
editContentRef.current = next;
|
|
26596
|
+
},
|
|
26597
|
+
applyLinkByKey,
|
|
26598
|
+
postToParent: postToParent2
|
|
26599
|
+
};
|
|
26600
|
+
const onPageMessage = (e) => {
|
|
26601
|
+
if (e.data?.type === "ow:page-created") {
|
|
26602
|
+
const { path, title } = e.data;
|
|
26603
|
+
if (typeof path !== "string" || !path) return;
|
|
26604
|
+
if (addNavLinkForPage({ path, title: typeof title === "string" && title ? title : path }, deps)) {
|
|
26605
|
+
enforceLinkHrefs();
|
|
26606
|
+
}
|
|
26607
|
+
return;
|
|
26608
|
+
}
|
|
26609
|
+
if (e.data?.type === "ow:page-renamed") {
|
|
26610
|
+
const { oldPath, newPath, oldTitle, newTitle } = e.data;
|
|
26611
|
+
if (typeof oldPath !== "string" || typeof newPath !== "string") return;
|
|
26612
|
+
const moved = retargetPageLinks(
|
|
26613
|
+
{
|
|
26614
|
+
oldPath,
|
|
26615
|
+
newPath,
|
|
26616
|
+
oldTitle: typeof oldTitle === "string" ? oldTitle : void 0,
|
|
26617
|
+
newTitle: typeof newTitle === "string" ? newTitle : void 0
|
|
26618
|
+
},
|
|
26619
|
+
deps
|
|
26620
|
+
);
|
|
26621
|
+
if (moved > 0) enforceLinkHrefs();
|
|
26622
|
+
}
|
|
26623
|
+
};
|
|
26624
|
+
window.addEventListener("message", onPageMessage);
|
|
26625
|
+
return () => window.removeEventListener("message", onPageMessage);
|
|
26626
|
+
}, [isEditMode, postToParent2]);
|
|
26234
26627
|
(0, import_react21.useEffect)(() => {
|
|
26235
26628
|
if (!isEditMode || shouldUseDevFixtures()) return;
|
|
26236
26629
|
void loadAllSectionsManifest().then((manifest) => {
|
|
@@ -27779,6 +28172,7 @@ function OhhwellsBridge() {
|
|
|
27779
28172
|
applyAiFooterFromContent(content);
|
|
27780
28173
|
if (typeof content[STYLE_STORE_KEY] === "string") {
|
|
27781
28174
|
stylesRef.current = content[STYLE_STORE_KEY];
|
|
28175
|
+
document.querySelectorAll('[data-ohw-editable="form"]').forEach((f) => markFormFields(f));
|
|
27782
28176
|
applyStylesToDom(parseStyleStore(content[STYLE_STORE_KEY]));
|
|
27783
28177
|
}
|
|
27784
28178
|
applyBrandChrome(content);
|
|
@@ -27789,12 +28183,12 @@ function OhhwellsBridge() {
|
|
|
27789
28183
|
if (key === "__ohw_sections") continue;
|
|
27790
28184
|
if (key === AI_SECTIONS_KEY) continue;
|
|
27791
28185
|
if (key === AI_FOOTER_KEY) continue;
|
|
28186
|
+
if (key === LOGO_PLACEHOLDER_KEY) continue;
|
|
28187
|
+
if (LOGO_IMAGE_KEYS.includes(key)) continue;
|
|
27792
28188
|
if (key === BRAND_KIT_KEY) continue;
|
|
27793
28189
|
if (key === STYLE_STORE_KEY) continue;
|
|
27794
28190
|
if (BRAND_CHROME_KEYS.has(key)) continue;
|
|
27795
|
-
if (key === LOGO_PLACEHOLDER_KEY) continue;
|
|
27796
28191
|
if (key === CUSTOM_CODE_AFTER_HEAD_KEY || key === CUSTOM_CODE_BEFORE_HEAD_KEY) continue;
|
|
27797
|
-
if (LOGO_IMAGE_KEYS.includes(key)) continue;
|
|
27798
28192
|
if (typeof content[AI_FOOTER_KEY] === "string" && content[AI_FOOTER_KEY] && isAiFooterOwnedContentKey(key)) {
|
|
27799
28193
|
continue;
|
|
27800
28194
|
}
|
|
@@ -28025,17 +28419,18 @@ function OhhwellsBridge() {
|
|
|
28025
28419
|
}
|
|
28026
28420
|
applyAiFooterFromContent(content);
|
|
28027
28421
|
if (typeof content[STYLE_STORE_KEY] === "string") {
|
|
28422
|
+
document.querySelectorAll('[data-ohw-editable="form"]').forEach((f) => markFormFields(f));
|
|
28028
28423
|
applyStylesToDom(parseStyleStore(content[STYLE_STORE_KEY]));
|
|
28029
28424
|
}
|
|
28030
28425
|
for (const [key, val] of Object.entries(content)) {
|
|
28031
28426
|
if (key === "__ohw_sections") continue;
|
|
28032
28427
|
if (key === AI_SECTIONS_KEY) continue;
|
|
28033
28428
|
if (key === AI_FOOTER_KEY) continue;
|
|
28429
|
+
if (key === LOGO_PLACEHOLDER_KEY) continue;
|
|
28430
|
+
if (LOGO_IMAGE_KEYS.includes(key)) continue;
|
|
28034
28431
|
if (key === BRAND_KIT_KEY) continue;
|
|
28035
28432
|
if (key === STYLE_STORE_KEY) continue;
|
|
28036
28433
|
if (BRAND_CHROME_KEYS.has(key)) continue;
|
|
28037
|
-
if (key === LOGO_PLACEHOLDER_KEY) continue;
|
|
28038
|
-
if (LOGO_IMAGE_KEYS.includes(key)) continue;
|
|
28039
28434
|
if (typeof content[AI_FOOTER_KEY] === "string" && content[AI_FOOTER_KEY] && isAiFooterOwnedContentKey(key)) {
|
|
28040
28435
|
continue;
|
|
28041
28436
|
}
|
|
@@ -28302,26 +28697,11 @@ function OhhwellsBridge() {
|
|
|
28302
28697
|
const t2 = setTimeout(measure, 500);
|
|
28303
28698
|
const ro = new ResizeObserver(schedule);
|
|
28304
28699
|
ro.observe(document.body);
|
|
28305
|
-
let lastWidth = window.innerWidth;
|
|
28306
|
-
let resizeTimers = [];
|
|
28307
|
-
const clearResizeTimers = () => {
|
|
28308
|
-
resizeTimers.forEach(clearTimeout);
|
|
28309
|
-
resizeTimers = [];
|
|
28310
|
-
};
|
|
28311
|
-
const handleResize = () => {
|
|
28312
|
-
if (window.innerWidth === lastWidth) return;
|
|
28313
|
-
lastWidth = window.innerWidth;
|
|
28314
|
-
clearResizeTimers();
|
|
28315
|
-
resizeTimers = HEIGHT_SETTLE_DELAYS.map((delay) => setTimeout(measure, delay));
|
|
28316
|
-
};
|
|
28317
|
-
window.addEventListener("resize", handleResize);
|
|
28318
28700
|
return () => {
|
|
28319
28701
|
clearTimeout(t1);
|
|
28320
28702
|
clearTimeout(t2);
|
|
28321
28703
|
if (raf != null) cancelAnimationFrame(raf);
|
|
28322
28704
|
ro.disconnect();
|
|
28323
|
-
clearResizeTimers();
|
|
28324
|
-
window.removeEventListener("resize", handleResize);
|
|
28325
28705
|
};
|
|
28326
28706
|
}, [pathname, isEditMode, postToParent2]);
|
|
28327
28707
|
(0, import_react21.useEffect)(() => {
|
|
@@ -28618,6 +28998,13 @@ function OhhwellsBridge() {
|
|
|
28618
28998
|
if (target.closest("[data-ohw-state-toggle]")) return;
|
|
28619
28999
|
if (target.closest("[data-ohw-max-badge]")) return;
|
|
28620
29000
|
if (isInsideLinkEditor(target)) return;
|
|
29001
|
+
if (isInsideFloatingPanel(target)) return;
|
|
29002
|
+
if (target.closest("[data-ohw-form-toolbar]")) return;
|
|
29003
|
+
if (target.closest(
|
|
29004
|
+
'[data-ohw-field-toolbar], [data-ohw-field-type-picker], [data-radix-popper-content-wrapper], [role="menu"], [data-slot="dropdown-menu-content"]'
|
|
29005
|
+
)) {
|
|
29006
|
+
return;
|
|
29007
|
+
}
|
|
28621
29008
|
if (selectedMediaElRef.current && !selectedMediaElRef.current.contains(target) && !target.closest("[data-ohw-media-overlay], [data-ohw-edit-chrome], [data-ohw-item-interaction]")) {
|
|
28622
29009
|
clearMediaSelectionRef.current();
|
|
28623
29010
|
}
|
|
@@ -28641,8 +29028,6 @@ function OhhwellsBridge() {
|
|
|
28641
29028
|
return;
|
|
28642
29029
|
}
|
|
28643
29030
|
}
|
|
28644
|
-
if (isInsideFloatingPanel(target)) return;
|
|
28645
|
-
if (target.closest("[data-ohw-form-toolbar]")) return;
|
|
28646
29031
|
const collectionItem = matchCollectionItemClick(target, collectionItemsRef.current);
|
|
28647
29032
|
if (collectionItem) {
|
|
28648
29033
|
e.preventDefault();
|
|
@@ -28654,11 +29039,6 @@ function OhhwellsBridge() {
|
|
|
28654
29039
|
});
|
|
28655
29040
|
return;
|
|
28656
29041
|
}
|
|
28657
|
-
if (target.closest(
|
|
28658
|
-
'[data-ohw-field-toolbar], [data-ohw-field-type-picker], [data-radix-popper-content-wrapper], [role="menu"], [data-slot="dropdown-menu-content"]'
|
|
28659
|
-
)) {
|
|
28660
|
-
return;
|
|
28661
|
-
}
|
|
28662
29042
|
{
|
|
28663
29043
|
const formEl = getFormElement(target);
|
|
28664
29044
|
const onSuccessText = target.closest(`[${SUCCESS_TEXT_ATTR}]`);
|
|
@@ -28812,9 +29192,13 @@ function OhhwellsBridge() {
|
|
|
28812
29192
|
if (isIconEditable(editable) && !getSocialItem(editable)) {
|
|
28813
29193
|
e.preventDefault();
|
|
28814
29194
|
e.stopPropagation();
|
|
28815
|
-
selectIconElementRef.current(editable);
|
|
28816
29195
|
const aiIcon = editable.hasAttribute("data-ai-icon");
|
|
28817
29196
|
const featureIcon = aiIcon && /\.features\.\d+\.icon$/.test(editable.dataset.ohwKey ?? "");
|
|
29197
|
+
if (aiIcon) {
|
|
29198
|
+
aiSectionApiRef.current?.selectFromElement(editable);
|
|
29199
|
+
} else {
|
|
29200
|
+
selectIconElementRef.current(editable);
|
|
29201
|
+
}
|
|
28818
29202
|
postToParentRef.current({
|
|
28819
29203
|
type: "ow:icon-pick",
|
|
28820
29204
|
key: editable.dataset.ohwKey ?? "",
|
|
@@ -29042,6 +29426,9 @@ function OhhwellsBridge() {
|
|
|
29042
29426
|
setHoveredItemRect(null);
|
|
29043
29427
|
hoveredNavContainerRef.current = null;
|
|
29044
29428
|
setHoveredNavContainerRect(null);
|
|
29429
|
+
siblingHintElRef.current = null;
|
|
29430
|
+
setSiblingHintRect(null);
|
|
29431
|
+
setSiblingHintRects([]);
|
|
29045
29432
|
return;
|
|
29046
29433
|
}
|
|
29047
29434
|
{
|
|
@@ -29162,7 +29549,6 @@ function OhhwellsBridge() {
|
|
|
29162
29549
|
hoveredNavContainerRef.current = null;
|
|
29163
29550
|
setHoveredNavContainerRect(null);
|
|
29164
29551
|
hoveredItemElRef.current = editable;
|
|
29165
|
-
setHoveredItemRect(isSelectedForHoverRef.current(editable) ? null : editable.getBoundingClientRect());
|
|
29166
29552
|
}
|
|
29167
29553
|
}
|
|
29168
29554
|
}
|
|
@@ -29872,7 +30258,11 @@ function OhhwellsBridge() {
|
|
|
29872
30258
|
};
|
|
29873
30259
|
const handleMouseMove = (e) => {
|
|
29874
30260
|
const { clientX, clientY } = e;
|
|
29875
|
-
if (pointOwnedByFloatingPanel(clientX, clientY))
|
|
30261
|
+
if (pointOwnedByFloatingPanel(clientX, clientY)) {
|
|
30262
|
+
dismissImageHover();
|
|
30263
|
+
clearImageHover();
|
|
30264
|
+
return;
|
|
30265
|
+
}
|
|
29876
30266
|
if (isNavDrawerOpen() && isPointOutsideOpenDrawer(clientX, clientY)) {
|
|
29877
30267
|
document.querySelectorAll("[data-ohw-hovered]").forEach((el) => el.removeAttribute("data-ohw-hovered"));
|
|
29878
30268
|
formHoverElRef.current = null;
|
|
@@ -29901,7 +30291,12 @@ function OhhwellsBridge() {
|
|
|
29901
30291
|
setHoveredItemRect(null);
|
|
29902
30292
|
hoveredNavContainerRef.current = null;
|
|
29903
30293
|
setHoveredNavContainerRect(null);
|
|
30294
|
+
siblingHintElRef.current = null;
|
|
30295
|
+
setSiblingHintRect(null);
|
|
30296
|
+
setSiblingHintRects([]);
|
|
29904
30297
|
dismissImageHover();
|
|
30298
|
+
clearImageHover();
|
|
30299
|
+
setSectionGap(null);
|
|
29905
30300
|
return;
|
|
29906
30301
|
}
|
|
29907
30302
|
if (probeSocialsRowAt(clientX, clientY)) return;
|
|
@@ -29913,7 +30308,11 @@ function OhhwellsBridge() {
|
|
|
29913
30308
|
if (e.data?.type !== "ow:pointer-sync") return;
|
|
29914
30309
|
const { clientX, clientY } = e.data;
|
|
29915
30310
|
if (typeof clientX !== "number" || typeof clientY !== "number") return;
|
|
29916
|
-
if (pointOwnedByFloatingPanel(clientX, clientY))
|
|
30311
|
+
if (pointOwnedByFloatingPanel(clientX, clientY)) {
|
|
30312
|
+
dismissImageHover();
|
|
30313
|
+
clearImageHover();
|
|
30314
|
+
return;
|
|
30315
|
+
}
|
|
29917
30316
|
if (isNavDrawerOpen() && isPointOutsideOpenDrawer(clientX, clientY)) return;
|
|
29918
30317
|
if (probeSocialsRowAt(clientX, clientY)) return;
|
|
29919
30318
|
probeSectionGapAt(clientX, clientY);
|
|
@@ -30293,6 +30692,7 @@ function OhhwellsBridge() {
|
|
|
30293
30692
|
applyAiFooterFromContent(content);
|
|
30294
30693
|
if (typeof content[STYLE_STORE_KEY] === "string") {
|
|
30295
30694
|
stylesRef.current = content[STYLE_STORE_KEY];
|
|
30695
|
+
document.querySelectorAll('[data-ohw-editable="form"]').forEach((f) => markFormFields(f));
|
|
30296
30696
|
applyStylesToDom(parseStyleStore(content[STYLE_STORE_KEY]));
|
|
30297
30697
|
}
|
|
30298
30698
|
applyBrandChrome(content);
|
|
@@ -30307,12 +30707,12 @@ function OhhwellsBridge() {
|
|
|
30307
30707
|
}
|
|
30308
30708
|
if (key === AI_SECTIONS_KEY) continue;
|
|
30309
30709
|
if (key === AI_FOOTER_KEY) continue;
|
|
30710
|
+
if (key === LOGO_PLACEHOLDER_KEY) continue;
|
|
30711
|
+
if (LOGO_IMAGE_KEYS.includes(key) && !String(val ?? "").trim()) continue;
|
|
30310
30712
|
if (key === BRAND_KIT_KEY) continue;
|
|
30311
30713
|
if (key === STYLE_STORE_KEY) continue;
|
|
30312
30714
|
if (BRAND_CHROME_KEYS.has(key)) continue;
|
|
30313
|
-
if (key === LOGO_PLACEHOLDER_KEY) continue;
|
|
30314
30715
|
if (key === CUSTOM_CODE_AFTER_HEAD_KEY || key === CUSTOM_CODE_BEFORE_HEAD_KEY) continue;
|
|
30315
|
-
if (LOGO_IMAGE_KEYS.includes(key) && !String(val ?? "").trim()) continue;
|
|
30316
30716
|
if (typeof content[AI_FOOTER_KEY] === "string" && content[AI_FOOTER_KEY] && isAiFooterOwnedContentKey(key)) {
|
|
30317
30717
|
continue;
|
|
30318
30718
|
}
|
|
@@ -30948,6 +31348,12 @@ function OhhwellsBridge() {
|
|
|
30948
31348
|
closeLinkPopoverRef.current();
|
|
30949
31349
|
return;
|
|
30950
31350
|
}
|
|
31351
|
+
if (floatingPanelOpenRef.current) {
|
|
31352
|
+
setFloatingPanelRef.current(null);
|
|
31353
|
+
deselectRef.current();
|
|
31354
|
+
deactivateRef.current();
|
|
31355
|
+
return;
|
|
31356
|
+
}
|
|
30951
31357
|
deselectRef.current();
|
|
30952
31358
|
deactivateRef.current();
|
|
30953
31359
|
clearMediaSelectionRef.current();
|
|
@@ -31328,13 +31734,15 @@ function OhhwellsBridge() {
|
|
|
31328
31734
|
if (e.data?.type !== "ow:collect-section") return;
|
|
31329
31735
|
const sectionId = e.data.sectionId;
|
|
31330
31736
|
if (typeof sectionId !== "string" || !sectionId) return;
|
|
31331
|
-
const
|
|
31332
|
-
|
|
31737
|
+
const escapedSectionId = CSS.escape(sectionId);
|
|
31738
|
+
const instanceEl = document.querySelector(
|
|
31739
|
+
`[data-ohw-instance="${escapedSectionId}"]`
|
|
31333
31740
|
);
|
|
31741
|
+
const foundEl = instanceEl ? sectionElementOf(instanceEl) : document.querySelector(`[data-ohw-section="${escapedSectionId}"]`);
|
|
31334
31742
|
const sectionEl = foundEl && !foundEl.hasAttribute("data-ohw-ai-template-hidden") && !foundEl.hasAttribute("data-ohw-ai-removed") && !foundEl.hasAttribute("data-ohw-ai-replaced-by") ? foundEl : null;
|
|
31335
31743
|
const nodes = sectionEl ? collectEditableNodes(void 0, sectionEl).filter(
|
|
31336
31744
|
(n) => n.key && !n.key.startsWith("__ohw_") && !["meta", "sections", "video-setting"].includes(n.type)
|
|
31337
|
-
).map((n) => ({ ...n, text: n.text ?? "", type: normalizeAiNodeType(n.type) })) : [];
|
|
31745
|
+
).map((n) => ({ ...n, text: n.text ?? "", type: normalizeAiNodeType(n.type) })).map((n) => withNodeFontSize(n, sectionEl)) : [];
|
|
31338
31746
|
const items = sectionEl ? collectItemGroups(sectionEl) : [];
|
|
31339
31747
|
const box = sectionEl?.getBoundingClientRect();
|
|
31340
31748
|
const rect = box ? {
|
|
@@ -31343,7 +31751,11 @@ function OhhwellsBridge() {
|
|
|
31343
31751
|
width: box.width,
|
|
31344
31752
|
height: box.height
|
|
31345
31753
|
} : null;
|
|
31346
|
-
const settings = resolveSectionSettingsContext(
|
|
31754
|
+
const settings = resolveSectionSettingsContext(
|
|
31755
|
+
sectionId,
|
|
31756
|
+
aiSectionsRef.current,
|
|
31757
|
+
stylesRef.current
|
|
31758
|
+
);
|
|
31347
31759
|
const tree = resolveSectionTree(sectionId, aiSectionsRef.current);
|
|
31348
31760
|
postToParentRef.current({
|
|
31349
31761
|
type: "ow:section-nodes",
|
|
@@ -31777,10 +32189,10 @@ function OhhwellsBridge() {
|
|
|
31777
32189
|
window.removeEventListener("message", handleDuplicateSection);
|
|
31778
32190
|
window.removeEventListener("message", handleDeactivate);
|
|
31779
32191
|
window.removeEventListener("message", handleSelectNav);
|
|
31780
|
-
document.documentElement.removeAttribute("data-ohw-panel-dragging");
|
|
31781
32192
|
window.removeEventListener("message", handleToastAction);
|
|
31782
32193
|
window.removeEventListener("message", handleFormCount);
|
|
31783
32194
|
window.removeEventListener("message", handleUiEscape);
|
|
32195
|
+
document.documentElement.removeAttribute("data-ohw-panel-dragging");
|
|
31784
32196
|
autoSaveTimers.current.forEach(clearTimeout);
|
|
31785
32197
|
autoSaveTimers.current.clear();
|
|
31786
32198
|
if (imageUnhoverTimerRef.current) clearTimeout(imageUnhoverTimerRef.current);
|
|
@@ -32074,7 +32486,7 @@ function OhhwellsBridge() {
|
|
|
32074
32486
|
postToParent2({
|
|
32075
32487
|
type: "ow:ready",
|
|
32076
32488
|
version: "1",
|
|
32077
|
-
bridgeVersion: "0.1.
|
|
32489
|
+
bridgeVersion: "0.1.160-next.427",
|
|
32078
32490
|
path: pathname,
|
|
32079
32491
|
nodes: collectEditableNodes(editContentRef.current),
|
|
32080
32492
|
sections
|