@ohhwells/bridge 0.1.76-next.230 → 0.1.77
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +211 -1210
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +4 -18
- package/dist/index.d.ts +4 -18
- package/dist/index.js +211 -1209
- package/dist/index.js.map +1 -1
- package/dist/styles.css +0 -58
- package/package.json +3 -8
- package/dist/pages.cjs +0 -141
- package/dist/pages.cjs.map +0 -1
- package/dist/pages.d.cts +0 -45
- package/dist/pages.d.ts +0 -45
- package/dist/pages.js +0 -107
- package/dist/pages.js.map +0 -1
package/dist/index.cjs
CHANGED
|
@@ -46,7 +46,6 @@ __export(index_exports, {
|
|
|
46
46
|
DropdownMenuItem: () => DropdownMenuItem,
|
|
47
47
|
DropdownMenuSeparator: () => DropdownMenuSeparator,
|
|
48
48
|
DropdownMenuTrigger: () => DropdownMenuTrigger,
|
|
49
|
-
EmptySection: () => EmptySection,
|
|
50
49
|
ItemActionToolbar: () => ItemActionToolbar,
|
|
51
50
|
ItemInteractionLayer: () => ItemInteractionLayer,
|
|
52
51
|
LinkEditorPanel: () => LinkEditorPanel,
|
|
@@ -157,12 +156,7 @@ function parseAiSectionsState(raw) {
|
|
|
157
156
|
media: entry.media && typeof entry.media === "object" ? entry.media : {}
|
|
158
157
|
}));
|
|
159
158
|
const removed = Array.isArray(parsed.removed) ? parsed.removed.filter((id) => typeof id === "string" && id.length > 0) : [];
|
|
160
|
-
return {
|
|
161
|
-
v: 1,
|
|
162
|
-
sections,
|
|
163
|
-
...removed.length ? { removed } : {},
|
|
164
|
-
...parsed.hideTemplate === true ? { hideTemplate: true } : {}
|
|
165
|
-
};
|
|
159
|
+
return { v: 1, sections, ...removed.length ? { removed } : {} };
|
|
166
160
|
} catch {
|
|
167
161
|
return EMPTY_AI_SECTIONS;
|
|
168
162
|
}
|
|
@@ -175,7 +169,6 @@ function applyTreeToState(state, payload) {
|
|
|
175
169
|
const entry = {
|
|
176
170
|
id: payload.id,
|
|
177
171
|
label: payload.label ?? "Generated section",
|
|
178
|
-
...typeof payload.path === "string" && payload.path ? { path: payload.path } : {},
|
|
179
172
|
afterSection: payload.mode === "insert" && !insertBefore ? payload.targetSectionId ?? null : null,
|
|
180
173
|
...insertBefore && payload.targetSectionId ? { beforeSection: payload.targetSectionId } : {},
|
|
181
174
|
...payload.mode === "replace" && payload.targetSectionId ? { replaces: payload.targetSectionId } : {},
|
|
@@ -198,317 +191,6 @@ function deleteSectionFromState(state, sectionId) {
|
|
|
198
191
|
return { ...state, v: 1, sections: state.sections, removed: [...removed, sectionId] };
|
|
199
192
|
}
|
|
200
193
|
|
|
201
|
-
// src/lib/brand-chrome.ts
|
|
202
|
-
var BRAND_NAME_KEY = "__ohw_brand_name";
|
|
203
|
-
var BRAND_TITLE_KEY = "__ohw_site_title";
|
|
204
|
-
var BRAND_FAVICON_LETTER_KEY = "__ohw_favicon_letter";
|
|
205
|
-
var BRAND_CHROME_KEYS = /* @__PURE__ */ new Set([
|
|
206
|
-
BRAND_NAME_KEY,
|
|
207
|
-
BRAND_TITLE_KEY,
|
|
208
|
-
BRAND_FAVICON_LETTER_KEY
|
|
209
|
-
]);
|
|
210
|
-
function upsertMeta(selector, attr, token, value) {
|
|
211
|
-
let el = document.head.querySelector(selector);
|
|
212
|
-
if (!el) {
|
|
213
|
-
el = document.createElement("meta");
|
|
214
|
-
el.setAttribute(attr, token);
|
|
215
|
-
document.head.appendChild(el);
|
|
216
|
-
}
|
|
217
|
-
if (el.getAttribute("content") !== value) el.setAttribute("content", value);
|
|
218
|
-
}
|
|
219
|
-
function escapeXml(value) {
|
|
220
|
-
return value.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """).replace(/'/g, "'");
|
|
221
|
-
}
|
|
222
|
-
function applyLetterFavicon(letter) {
|
|
223
|
-
const svg = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64"><rect width="64" height="64" rx="12" fill="#111827"/><text x="32" y="46" font-family="system-ui,-apple-system,Segoe UI,sans-serif" font-size="40" font-weight="700" text-anchor="middle" fill="#ffffff">${escapeXml(letter)}</text></svg>`;
|
|
224
|
-
const href = `data:image/svg+xml,${encodeURIComponent(svg)}`;
|
|
225
|
-
let link = document.head.querySelector('link[rel="icon"]');
|
|
226
|
-
if (!link) {
|
|
227
|
-
link = document.createElement("link");
|
|
228
|
-
link.rel = "icon";
|
|
229
|
-
document.head.appendChild(link);
|
|
230
|
-
}
|
|
231
|
-
link.type = "image/svg+xml";
|
|
232
|
-
if (link.href !== href) link.href = href;
|
|
233
|
-
}
|
|
234
|
-
function applyBrandChrome(content) {
|
|
235
|
-
const name = content[BRAND_NAME_KEY];
|
|
236
|
-
if (typeof name === "string" && name.length > 0) {
|
|
237
|
-
document.querySelectorAll("[data-ohw-wordmark]").forEach((el) => {
|
|
238
|
-
if (el.textContent !== name) el.textContent = name;
|
|
239
|
-
if (el.getAttribute("title") !== name) el.setAttribute("title", name);
|
|
240
|
-
});
|
|
241
|
-
}
|
|
242
|
-
const title = content[BRAND_TITLE_KEY];
|
|
243
|
-
if (typeof title === "string" && title.length > 0) {
|
|
244
|
-
if (document.title !== title) document.title = title;
|
|
245
|
-
upsertMeta('meta[property="og:title"]', "property", "og:title", title);
|
|
246
|
-
upsertMeta('meta[name="twitter:title"]', "name", "twitter:title", title);
|
|
247
|
-
}
|
|
248
|
-
const letter = content[BRAND_FAVICON_LETTER_KEY];
|
|
249
|
-
if (typeof letter === "string" && letter.length > 0) {
|
|
250
|
-
applyLetterFavicon(letter);
|
|
251
|
-
}
|
|
252
|
-
}
|
|
253
|
-
|
|
254
|
-
// src/lib/brand-kit.ts
|
|
255
|
-
var BRAND_KIT_KEY = "__ohw_brand";
|
|
256
|
-
var BRAND_VAR_PREFIX = "--ohw-brand-";
|
|
257
|
-
var BRAND_VAR_NAMES = ["primary", "accent", "light", "dark", "surface", "border", "muted"].map(
|
|
258
|
-
(role) => `${BRAND_VAR_PREFIX}${role}`
|
|
259
|
-
);
|
|
260
|
-
var FONT_VARS = {
|
|
261
|
-
heading: ["--font-heading", "--font-display", "--brand-font-heading"],
|
|
262
|
-
body: ["--font-body", "--brand-font-body"]
|
|
263
|
-
};
|
|
264
|
-
var BRAND_FONT_LINK_ID = "ohw-brand-fonts";
|
|
265
|
-
function brandColorVars(kit) {
|
|
266
|
-
const { dark, primary, accent, light } = kit.palette;
|
|
267
|
-
const mix = (a, aPct, b) => `color-mix(in srgb, ${a} ${aPct}%, ${b})`;
|
|
268
|
-
return {
|
|
269
|
-
[`${BRAND_VAR_PREFIX}primary`]: primary,
|
|
270
|
-
[`${BRAND_VAR_PREFIX}accent`]: accent,
|
|
271
|
-
[`${BRAND_VAR_PREFIX}light`]: light,
|
|
272
|
-
[`${BRAND_VAR_PREFIX}dark`]: dark,
|
|
273
|
-
[`${BRAND_VAR_PREFIX}surface`]: mix(light, 95, dark),
|
|
274
|
-
[`${BRAND_VAR_PREFIX}border`]: mix(light, 85, dark),
|
|
275
|
-
[`${BRAND_VAR_PREFIX}muted`]: mix(dark, 62, light)
|
|
276
|
-
};
|
|
277
|
-
}
|
|
278
|
-
function parseBrandKit(raw) {
|
|
279
|
-
if (!raw) return null;
|
|
280
|
-
try {
|
|
281
|
-
const parsed = JSON.parse(raw);
|
|
282
|
-
const p = parsed?.palette;
|
|
283
|
-
const f = parsed?.fonts;
|
|
284
|
-
if (!p || !f || typeof p.dark !== "string" || typeof p.primary !== "string" || typeof p.accent !== "string" || typeof p.light !== "string" || typeof f.heading !== "string" || typeof f.body !== "string") {
|
|
285
|
-
return null;
|
|
286
|
-
}
|
|
287
|
-
return {
|
|
288
|
-
palette: { dark: p.dark, primary: p.primary, accent: p.accent, light: p.light },
|
|
289
|
-
fonts: { heading: f.heading, body: f.body }
|
|
290
|
-
};
|
|
291
|
-
} catch {
|
|
292
|
-
return null;
|
|
293
|
-
}
|
|
294
|
-
}
|
|
295
|
-
function familyOf(stack) {
|
|
296
|
-
const first = stack.split(",")[0]?.trim() ?? "";
|
|
297
|
-
return first.replace(/^['"]|['"]$/g, "");
|
|
298
|
-
}
|
|
299
|
-
function loadBrandFonts(families) {
|
|
300
|
-
const unique = [...new Set(families.map((f) => f.trim()).filter(Boolean))];
|
|
301
|
-
if (unique.length === 0) return;
|
|
302
|
-
const spec = unique.map((f) => `${f.replace(/ /g, "+")}:400,500,600,700`).join("|");
|
|
303
|
-
const href = `https://fonts.googleapis.com/css?family=${spec}&display=swap`;
|
|
304
|
-
let link = document.getElementById(BRAND_FONT_LINK_ID);
|
|
305
|
-
if (!link) {
|
|
306
|
-
link = document.createElement("link");
|
|
307
|
-
link.id = BRAND_FONT_LINK_ID;
|
|
308
|
-
link.rel = "stylesheet";
|
|
309
|
-
document.head.appendChild(link);
|
|
310
|
-
}
|
|
311
|
-
if (link.href !== href) link.href = href;
|
|
312
|
-
}
|
|
313
|
-
function applyBrandToDom(kit) {
|
|
314
|
-
const root = document.documentElement;
|
|
315
|
-
if (!kit) {
|
|
316
|
-
for (const name of BRAND_VAR_NAMES) root.style.removeProperty(name);
|
|
317
|
-
for (const name of [...FONT_VARS.heading, ...FONT_VARS.body]) root.style.removeProperty(name);
|
|
318
|
-
document.getElementById(BRAND_FONT_LINK_ID)?.remove();
|
|
319
|
-
return;
|
|
320
|
-
}
|
|
321
|
-
for (const [name, value] of Object.entries(brandColorVars(kit))) root.style.setProperty(name, value);
|
|
322
|
-
for (const name of FONT_VARS.heading) root.style.setProperty(name, kit.fonts.heading);
|
|
323
|
-
for (const name of FONT_VARS.body) root.style.setProperty(name, kit.fonts.body);
|
|
324
|
-
loadBrandFonts([familyOf(kit.fonts.heading), familyOf(kit.fonts.body)]);
|
|
325
|
-
}
|
|
326
|
-
|
|
327
|
-
// src/lib/section-styles.ts
|
|
328
|
-
var STYLE_STORE_KEY = "__ohw_styles";
|
|
329
|
-
var STYLE_SHEET_ID = "ohw-section-styles";
|
|
330
|
-
function parseStyleStore(raw) {
|
|
331
|
-
if (!raw) return null;
|
|
332
|
-
try {
|
|
333
|
-
const parsed = JSON.parse(raw);
|
|
334
|
-
if (parsed?.v !== 1) return null;
|
|
335
|
-
return {
|
|
336
|
-
v: 1,
|
|
337
|
-
sections: typeof parsed.sections === "object" && parsed.sections ? parsed.sections : {},
|
|
338
|
-
nodes: typeof parsed.nodes === "object" && parsed.nodes ? parsed.nodes : {}
|
|
339
|
-
};
|
|
340
|
-
} catch {
|
|
341
|
-
return null;
|
|
342
|
-
}
|
|
343
|
-
}
|
|
344
|
-
var BG_VALUES = {
|
|
345
|
-
surface: "color-mix(in srgb, var(--ohw-brand-light, var(--color-light, #ECECEB)) 94%, var(--ohw-brand-dark, var(--color-dark, #0C0A09)))",
|
|
346
|
-
accent: "var(--ohw-brand-primary, var(--color-primary, #0078E5))",
|
|
347
|
-
"accent-soft": "color-mix(in srgb, var(--ohw-brand-primary, var(--color-primary, #0078E5)) 12%, var(--ohw-brand-light, var(--color-light, #FFFFFF)))"
|
|
348
|
-
};
|
|
349
|
-
var HEADLINE_SIZES = { md: 24, lg: 32, xl: 40, display: 56 };
|
|
350
|
-
function styleSheetCss() {
|
|
351
|
-
const rules = [];
|
|
352
|
-
for (const [tone, value] of Object.entries(BG_VALUES)) {
|
|
353
|
-
rules.push(`[data-ohw-style-bg="${tone}"] { background: ${value} !important; }`);
|
|
354
|
-
}
|
|
355
|
-
rules.push(
|
|
356
|
-
`[data-ohw-style-bg="accent"] { color: var(--ohw-brand-light, var(--color-light, #FFFFFF)) !important; }`
|
|
357
|
-
);
|
|
358
|
-
rules.push(
|
|
359
|
-
`[data-ohw-style-distribution="space-between"] { display: flex !important; flex-direction: column; justify-content: space-between; }`,
|
|
360
|
-
`[data-ohw-style-distribution="center"] { display: flex !important; flex-direction: column; justify-content: center; }`
|
|
361
|
-
);
|
|
362
|
-
for (const [scale, size] of Object.entries(HEADLINE_SIZES)) {
|
|
363
|
-
rules.push(
|
|
364
|
-
`[data-ohw-style-headline="${scale}"] :is(h1, h2, h3) { font-size: ${size}px !important; line-height: 1.15 !important; }`
|
|
365
|
-
);
|
|
366
|
-
}
|
|
367
|
-
rules.push(
|
|
368
|
-
`[data-ohw-style-aspect="fill-height"] img { height: 100% !important; aspect-ratio: auto !important; object-fit: cover; }`
|
|
369
|
-
);
|
|
370
|
-
for (const aspect of ["1:1", "4:5", "3:4", "3:2", "16:9", "2:1", "3:1"]) {
|
|
371
|
-
rules.push(
|
|
372
|
-
`[data-ohw-style-aspect="${aspect.replace(":", "-")}"] img { aspect-ratio: ${aspect.replace(":", " / ")} !important; height: auto !important; object-fit: cover; }`
|
|
373
|
-
);
|
|
374
|
-
}
|
|
375
|
-
const pad = { tight: 40, balanced: 64, airy: 96 };
|
|
376
|
-
for (const [spacing, px] of Object.entries(pad)) {
|
|
377
|
-
rules.push(
|
|
378
|
-
`[data-ohw-style-spacing="${spacing}"] { padding-top: ${px}px !important; padding-bottom: ${px}px !important; }`
|
|
379
|
-
);
|
|
380
|
-
}
|
|
381
|
-
return rules.join("\n");
|
|
382
|
-
}
|
|
383
|
-
var STYLE_FONT_LINK_ID = "ohw-style-fonts";
|
|
384
|
-
function loadStyleFonts(families) {
|
|
385
|
-
const unique = [...new Set(families.map((f) => f.trim()).filter(Boolean))];
|
|
386
|
-
const existing = document.getElementById(STYLE_FONT_LINK_ID);
|
|
387
|
-
if (unique.length === 0) {
|
|
388
|
-
existing?.remove();
|
|
389
|
-
return;
|
|
390
|
-
}
|
|
391
|
-
const spec = unique.map((f) => `${f.replace(/ /g, "+")}:400,500,600,700`).join("|");
|
|
392
|
-
const href = `https://fonts.googleapis.com/css?family=${spec}&display=swap`;
|
|
393
|
-
let link = existing;
|
|
394
|
-
if (!link) {
|
|
395
|
-
link = document.createElement("link");
|
|
396
|
-
link.id = STYLE_FONT_LINK_ID;
|
|
397
|
-
link.rel = "stylesheet";
|
|
398
|
-
document.head.appendChild(link);
|
|
399
|
-
}
|
|
400
|
-
if (link.href !== href) link.href = href;
|
|
401
|
-
}
|
|
402
|
-
var SECTION_ATTRS = {
|
|
403
|
-
sectionBackground: "data-ohw-style-bg",
|
|
404
|
-
textDistribution: "data-ohw-style-distribution",
|
|
405
|
-
headlineScale: "data-ohw-style-headline",
|
|
406
|
-
imageAspect: "data-ohw-style-aspect",
|
|
407
|
-
spacing: "data-ohw-style-spacing"
|
|
408
|
-
};
|
|
409
|
-
var NODE_WROTE_ATTR = "data-ohw-style-node";
|
|
410
|
-
var NODE_PROPS = ["color", "font-family", "font-size", "background"];
|
|
411
|
-
function saveInline(el, prop) {
|
|
412
|
-
const attr = `data-ohw-style-prev-${prop}`;
|
|
413
|
-
if (!el.hasAttribute(attr)) el.setAttribute(attr, el.style.getPropertyValue(prop));
|
|
414
|
-
}
|
|
415
|
-
function restoreInline(el, prop) {
|
|
416
|
-
const attr = `data-ohw-style-prev-${prop}`;
|
|
417
|
-
if (!el.hasAttribute(attr)) return;
|
|
418
|
-
const prev = el.getAttribute(attr) ?? "";
|
|
419
|
-
if (prev) el.style.setProperty(prop, prev);
|
|
420
|
-
else el.style.removeProperty(prop);
|
|
421
|
-
el.removeAttribute(attr);
|
|
422
|
-
}
|
|
423
|
-
function ensureStyleSheet() {
|
|
424
|
-
let el = document.getElementById(STYLE_SHEET_ID);
|
|
425
|
-
if (!el) {
|
|
426
|
-
el = document.createElement("style");
|
|
427
|
-
el.id = STYLE_SHEET_ID;
|
|
428
|
-
document.head.appendChild(el);
|
|
429
|
-
}
|
|
430
|
-
const css = styleSheetCss();
|
|
431
|
-
if (el.textContent !== css) el.textContent = css;
|
|
432
|
-
}
|
|
433
|
-
function clearSectionAttrs(root) {
|
|
434
|
-
for (const attr of Object.values(SECTION_ATTRS)) {
|
|
435
|
-
for (const el of Array.from(root.querySelectorAll(`[${attr}]`))) el.removeAttribute(attr);
|
|
436
|
-
}
|
|
437
|
-
for (const el of Array.from(root.querySelectorAll("[data-ohw-style-bgcolor]"))) {
|
|
438
|
-
restoreInline(el, "background");
|
|
439
|
-
el.removeAttribute("data-ohw-style-bgcolor");
|
|
440
|
-
}
|
|
441
|
-
}
|
|
442
|
-
function clearNodeProps(root) {
|
|
443
|
-
for (const el of Array.from(root.querySelectorAll(`[${NODE_WROTE_ATTR}]`))) {
|
|
444
|
-
const h = el;
|
|
445
|
-
for (const prop of NODE_PROPS) restoreInline(h, prop);
|
|
446
|
-
h.removeAttribute(NODE_WROTE_ATTR);
|
|
447
|
-
}
|
|
448
|
-
}
|
|
449
|
-
function buttonSurfaceOf(el) {
|
|
450
|
-
return el.closest("a, button") ?? el;
|
|
451
|
-
}
|
|
452
|
-
function applyStylesToDom(store) {
|
|
453
|
-
ensureStyleSheet();
|
|
454
|
-
clearSectionAttrs(document);
|
|
455
|
-
clearNodeProps(document);
|
|
456
|
-
loadStyleFonts(
|
|
457
|
-
store ? Object.values(store.nodes).flatMap((n) => n.fontFamily ? [n.fontFamily] : []) : []
|
|
458
|
-
);
|
|
459
|
-
if (!store) return;
|
|
460
|
-
for (const [sectionId, override] of Object.entries(store.sections)) {
|
|
461
|
-
const sections = document.querySelectorAll(
|
|
462
|
-
`[data-ohw-section="${CSS.escape(sectionId)}"]`
|
|
463
|
-
);
|
|
464
|
-
for (const section of Array.from(sections)) {
|
|
465
|
-
for (const [prop, attr] of Object.entries(SECTION_ATTRS)) {
|
|
466
|
-
const value = override[prop];
|
|
467
|
-
if (value === void 0) continue;
|
|
468
|
-
if (prop === "sectionBackground" && override.sectionBackgroundColor !== void 0) continue;
|
|
469
|
-
section.setAttribute(attr, String(value).replace(":", "-"));
|
|
470
|
-
}
|
|
471
|
-
if (override.sectionBackgroundColor !== void 0) {
|
|
472
|
-
saveInline(section, "background");
|
|
473
|
-
section.style.setProperty("background", override.sectionBackgroundColor, "important");
|
|
474
|
-
section.setAttribute("data-ohw-style-bgcolor", "");
|
|
475
|
-
}
|
|
476
|
-
}
|
|
477
|
-
}
|
|
478
|
-
for (const [key, override] of Object.entries(store.nodes)) {
|
|
479
|
-
const nodes = document.querySelectorAll(`[data-ohw-key="${CSS.escape(key)}"]`);
|
|
480
|
-
for (const el of Array.from(nodes)) {
|
|
481
|
-
if (override.color !== void 0) {
|
|
482
|
-
saveInline(el, "color");
|
|
483
|
-
el.style.setProperty("color", override.color, "important");
|
|
484
|
-
el.setAttribute(NODE_WROTE_ATTR, "");
|
|
485
|
-
}
|
|
486
|
-
if (override.fontFamily !== void 0) {
|
|
487
|
-
saveInline(el, "font-family");
|
|
488
|
-
el.style.setProperty("font-family", `'${override.fontFamily}'`, "important");
|
|
489
|
-
el.setAttribute(NODE_WROTE_ATTR, "");
|
|
490
|
-
}
|
|
491
|
-
if (override.fontSize !== void 0) {
|
|
492
|
-
saveInline(el, "font-size");
|
|
493
|
-
el.style.setProperty("font-size", `${override.fontSize}px`, "important");
|
|
494
|
-
el.setAttribute(NODE_WROTE_ATTR, "");
|
|
495
|
-
}
|
|
496
|
-
if (override.buttonBackground !== void 0 || override.buttonText !== void 0) {
|
|
497
|
-
const surface = buttonSurfaceOf(el);
|
|
498
|
-
if (override.buttonBackground !== void 0) {
|
|
499
|
-
saveInline(surface, "background");
|
|
500
|
-
surface.style.setProperty("background", override.buttonBackground, "important");
|
|
501
|
-
}
|
|
502
|
-
if (override.buttonText !== void 0) {
|
|
503
|
-
saveInline(surface, "color");
|
|
504
|
-
surface.style.setProperty("color", override.buttonText, "important");
|
|
505
|
-
}
|
|
506
|
-
surface.setAttribute(NODE_WROTE_ATTR, "");
|
|
507
|
-
}
|
|
508
|
-
}
|
|
509
|
-
}
|
|
510
|
-
}
|
|
511
|
-
|
|
512
194
|
// src/ui/ai-tree/aiSectionsManager.tsx
|
|
513
195
|
var import_react_dom = require("react-dom");
|
|
514
196
|
var import_client = require("react-dom/client");
|
|
@@ -523,8 +205,7 @@ function lucideByName(name) {
|
|
|
523
205
|
}
|
|
524
206
|
var typeStyle = (spec, font) => ({
|
|
525
207
|
fontFamily: font,
|
|
526
|
-
|
|
527
|
-
fontSize: spec.size >= 24 ? `clamp(${Math.max(18, Math.round(spec.size * 0.6))}px, ${(spec.size / 9).toFixed(2)}vw, ${spec.size}px)` : spec.size,
|
|
208
|
+
fontSize: spec.size,
|
|
528
209
|
lineHeight: spec.line,
|
|
529
210
|
fontWeight: spec.weight
|
|
530
211
|
});
|
|
@@ -533,60 +214,12 @@ var featureLines = (value) => value.split(/\n|<br\s*\/?>/i).map((line) => line.t
|
|
|
533
214
|
var CHECK_MASK = `data:image/svg+xml,${encodeURIComponent(
|
|
534
215
|
'<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="black" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M20 6 9 17l-5-5"/></svg>'
|
|
535
216
|
)}`;
|
|
536
|
-
var AI_MOBILE_CSS = [
|
|
537
|
-
"@media (max-width: 768px){",
|
|
538
|
-
"[data-ai-section]{overflow-x:hidden}",
|
|
539
|
-
"[data-ai-container]{padding:0 20px !important}",
|
|
540
|
-
"[data-ai-row]{display:flex !important;flex-direction:column !important;align-items:stretch !important}",
|
|
541
|
-
"[data-ai-cell]{width:100%;min-width:0}",
|
|
542
|
-
"[data-ai-grid]{grid-template-columns:1fr !important}",
|
|
543
|
-
// Group containers flatten to a column on phones; span placements come along for free.
|
|
544
|
-
"[data-ai-group]{display:flex !important;flex-direction:column !important}",
|
|
545
|
-
"[data-ai-group] > *{grid-column:auto !important}",
|
|
546
|
-
// The 50:50 form collapses to a single stacked column on phones.
|
|
547
|
-
"[data-ai-form]{grid-template-columns:1fr !important}",
|
|
548
|
-
"[data-ai-section] img{max-width:100%}",
|
|
549
|
-
"}",
|
|
550
|
-
"@media (min-width: 769px) and (max-width: 1024px){",
|
|
551
|
-
"[data-ai-grid]{grid-template-columns:repeat(2, 1fr) !important}",
|
|
552
|
-
"}"
|
|
553
|
-
].join("");
|
|
554
217
|
var FEATURE_LINE_CSS = [
|
|
555
218
|
"[data-ai-features]>div{position:relative;padding-left:40px;min-height:24px}",
|
|
556
219
|
'[data-ai-features]>div::before{content:"";position:absolute;left:0;top:1px;width:24px;height:24px;',
|
|
557
220
|
`background-color:currentColor;-webkit-mask:url("${CHECK_MASK}") no-repeat 0 0/24px 24px;`,
|
|
558
221
|
`mask:url("${CHECK_MASK}") no-repeat 0 0/24px 24px}`
|
|
559
222
|
].join("");
|
|
560
|
-
function hexLuminance(color) {
|
|
561
|
-
const m = /^#([0-9a-f]{6})$/i.exec(color.trim());
|
|
562
|
-
if (!m) return null;
|
|
563
|
-
const [r2, g, b] = [0, 2, 4].map((i) => {
|
|
564
|
-
const c = parseInt(m[1].slice(i, i + 2), 16) / 255;
|
|
565
|
-
return c <= 0.03928 ? c / 12.92 : Math.pow((c + 0.055) / 1.055, 2.4);
|
|
566
|
-
});
|
|
567
|
-
return 0.2126 * r2 + 0.7152 * g + 0.0722 * b;
|
|
568
|
-
}
|
|
569
|
-
function hexContrast(a, b) {
|
|
570
|
-
const la = hexLuminance(a);
|
|
571
|
-
const lb = hexLuminance(b);
|
|
572
|
-
if (la === null || lb === null) return null;
|
|
573
|
-
const [hi, lo] = la > lb ? [la, lb] : [lb, la];
|
|
574
|
-
return (hi + 0.05) / (lo + 0.05);
|
|
575
|
-
}
|
|
576
|
-
function accentBandContext(brand) {
|
|
577
|
-
const p = brand.palette;
|
|
578
|
-
const lightWins = (hexContrast(p.light, p.primary) ?? 99) >= (hexContrast(p.dark, p.primary) ?? 0);
|
|
579
|
-
if (lightWins) {
|
|
580
|
-
return {
|
|
581
|
-
brand: { ...brand, palette: { dark: p.light, primary: p.light, accent: p.light, light: p.primary } },
|
|
582
|
-
buttonLabel: p.primary
|
|
583
|
-
};
|
|
584
|
-
}
|
|
585
|
-
return {
|
|
586
|
-
brand: { ...brand, palette: { dark: p.dark, primary: p.dark, accent: p.dark, light: p.light } },
|
|
587
|
-
buttonLabel: p.light
|
|
588
|
-
};
|
|
589
|
-
}
|
|
590
223
|
function textAttrs(ctx, path) {
|
|
591
224
|
return ctx.keyFor ? { "data-ohw-key": ctx.keyFor(path), "data-ohw-editable": "text" } : {};
|
|
592
225
|
}
|
|
@@ -598,12 +231,7 @@ var AI_RESPONSIVE_CSS = [
|
|
|
598
231
|
"@media (max-width: 640px) {",
|
|
599
232
|
" [data-ai-responsive] [data-ai-grid] { grid-template-columns: 1fr !important; }",
|
|
600
233
|
" [data-ai-responsive] [data-ai-columns] > * { grid-column: 1 / -1 !important; }",
|
|
601
|
-
// Group containers flatten to a column on phones; span placements come along for free.
|
|
602
|
-
" [data-ai-responsive] [data-ai-group] { display: flex !important; flex-direction: column !important; }",
|
|
603
|
-
" [data-ai-responsive] [data-ai-group] > * { grid-column: auto !important; }",
|
|
604
234
|
" [data-ai-responsive] [data-ai-section-inner] { padding-left: 20px !important; padding-right: 20px !important; }",
|
|
605
|
-
" [data-ai-responsive] { overflow-x: hidden; }",
|
|
606
|
-
" [data-ai-responsive] img { max-width: 100%; }",
|
|
607
235
|
"}"
|
|
608
236
|
].join("\n");
|
|
609
237
|
var TRANSPARENT_PX = "data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7";
|
|
@@ -681,7 +309,7 @@ function ButtonEl({
|
|
|
681
309
|
}) {
|
|
682
310
|
const secondary = slots.variant === "secondary";
|
|
683
311
|
const href = str(slots.href);
|
|
684
|
-
const linkAttrs = ctx.keyFor && path ? { "data-ohw-href-key": ctx.keyFor(`${path}.href`)
|
|
312
|
+
const linkAttrs = ctx.keyFor && path ? { "data-ohw-href-key": ctx.keyFor(`${path}.href`) } : {};
|
|
685
313
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
686
314
|
"a",
|
|
687
315
|
{
|
|
@@ -697,7 +325,7 @@ function ButtonEl({
|
|
|
697
325
|
textDecoration: "none",
|
|
698
326
|
cursor: "pointer",
|
|
699
327
|
...typeStyle(AI_TREE_TOKENS.type.button, ctx.brand.fonts.body),
|
|
700
|
-
...secondary ? { border: `1px solid ${ctx.brand.palette.dark}`, color: ctx.brand.palette.dark } : { background: ctx.brand.palette.primary, color:
|
|
328
|
+
...secondary ? { border: `1px solid ${ctx.brand.palette.dark}`, color: ctx.brand.palette.dark } : { background: ctx.brand.palette.primary, color: AI_TREE_TOKENS.textPrimaryForeground }
|
|
701
329
|
},
|
|
702
330
|
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { ...path ? textAttrs(ctx, `${path}.label`) : {}, children: str(slots.label) })
|
|
703
331
|
}
|
|
@@ -1203,24 +831,7 @@ function CardBlock({ node, ctx, path }) {
|
|
|
1203
831
|
minWidth: 0
|
|
1204
832
|
},
|
|
1205
833
|
children: [
|
|
1206
|
-
media && (horizontal ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1207
|
-
"div",
|
|
1208
|
-
{
|
|
1209
|
-
style: (
|
|
1210
|
-
// An icon hugs its glyph — flex:1 gave a 48px icon half the card and pushed the
|
|
1211
|
-
// text to the far side. Photos keep the half-and-half split. The inset has no
|
|
1212
|
-
// inner padding (the photo split absorbed that), so the icon carries its own gap.
|
|
1213
|
-
/^(lucide|simple):/.test(mediaRef) ? {
|
|
1214
|
-
flexShrink: 0,
|
|
1215
|
-
display: "flex",
|
|
1216
|
-
alignItems: "center",
|
|
1217
|
-
padding: mediaInset,
|
|
1218
|
-
[mediaPosition === "right" ? "marginLeft" : "marginRight"]: 20
|
|
1219
|
-
} : { flex: 1, minWidth: 0, display: "flex", alignItems: "center", padding: mediaInset }
|
|
1220
|
-
),
|
|
1221
|
-
children: media
|
|
1222
|
-
}
|
|
1223
|
-
) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
834
|
+
media && (horizontal ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: { flex: 1, minWidth: 0, display: "flex", alignItems: "center", padding: mediaInset }, children: media }) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1224
835
|
"div",
|
|
1225
836
|
{
|
|
1226
837
|
style: /^(lucide|simple):/.test(mediaRef) ? { padding: `${AI_TREE_TOKENS.paddingBlock}px ${AI_TREE_TOKENS.paddingBlock}px 0` } : hasBg ? void 0 : { borderRadius: AI_TREE_TOKENS.radiusCard, overflow: "hidden" },
|
|
@@ -1311,44 +922,13 @@ function AccordionBlock({ node, ctx, path }) {
|
|
|
1311
922
|
) })
|
|
1312
923
|
] }, i)) });
|
|
1313
924
|
}
|
|
1314
|
-
function useIsMobile() {
|
|
1315
|
-
const [mobile, setMobile] = import_react.default.useState(
|
|
1316
|
-
() => typeof window !== "undefined" && window.matchMedia("(max-width: 768px)").matches
|
|
1317
|
-
);
|
|
1318
|
-
import_react.default.useEffect(() => {
|
|
1319
|
-
const mq = window.matchMedia("(max-width: 768px)");
|
|
1320
|
-
const update = () => setMobile(mq.matches);
|
|
1321
|
-
update();
|
|
1322
|
-
mq.addEventListener("change", update);
|
|
1323
|
-
return () => mq.removeEventListener("change", update);
|
|
1324
|
-
}, []);
|
|
1325
|
-
return mobile;
|
|
1326
|
-
}
|
|
1327
925
|
function Carousel({ items, itemsPerRow, ctx }) {
|
|
1328
|
-
const isMobile = useIsMobile();
|
|
1329
|
-
const perPage = isMobile ? 1 : itemsPerRow;
|
|
1330
|
-
const pages = Math.max(1, Math.ceil(items.length / perPage));
|
|
1331
926
|
const [page, setPage] = import_react.default.useState(0);
|
|
927
|
+
const pages = Math.max(1, Math.ceil(items.length / itemsPerRow));
|
|
1332
928
|
const current = Math.min(page, pages - 1);
|
|
1333
|
-
if (pages <= 1) {
|
|
1334
|
-
const cols = Math.max(1, Math.min(items.length, itemsPerRow));
|
|
1335
|
-
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1336
|
-
"div",
|
|
1337
|
-
{
|
|
1338
|
-
"data-ai-grid": String(cols),
|
|
1339
|
-
style: {
|
|
1340
|
-
display: "grid",
|
|
1341
|
-
gridTemplateColumns: `repeat(${cols}, 1fr)`,
|
|
1342
|
-
gap: AI_TREE_TOKENS.spacing8,
|
|
1343
|
-
alignItems: "start"
|
|
1344
|
-
},
|
|
1345
|
-
children: items
|
|
1346
|
-
}
|
|
1347
|
-
);
|
|
1348
|
-
}
|
|
1349
929
|
const pageGroups = Array.from(
|
|
1350
930
|
{ length: pages },
|
|
1351
|
-
(_, p) => items.slice(p *
|
|
931
|
+
(_, p) => items.slice(p * itemsPerRow, (p + 1) * itemsPerRow)
|
|
1352
932
|
);
|
|
1353
933
|
const chrome = (enabled) => ({
|
|
1354
934
|
border: `1px solid ${ctx.brand.palette.dark}`,
|
|
@@ -1373,69 +953,55 @@ function Carousel({ items, itemsPerRow, ctx }) {
|
|
|
1373
953
|
cursor: "pointer",
|
|
1374
954
|
padding: 0
|
|
1375
955
|
});
|
|
1376
|
-
|
|
1377
|
-
"div",
|
|
1378
|
-
|
|
1379
|
-
|
|
1380
|
-
|
|
1381
|
-
|
|
1382
|
-
|
|
1383
|
-
|
|
1384
|
-
|
|
956
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { "data-ai-carousel": "", style: { display: "flex", flexDirection: "column", gap: AI_TREE_TOKENS.spacing8, alignItems: "center" }, children: [
|
|
957
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: { display: "flex", alignItems: "center", gap: AI_TREE_TOKENS.spacing6, width: "100%" }, children: [
|
|
958
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
959
|
+
"button",
|
|
960
|
+
{
|
|
961
|
+
type: "button",
|
|
962
|
+
"aria-label": "Previous",
|
|
963
|
+
onClick: () => setPage((p) => Math.max(0, p - 1)),
|
|
964
|
+
style: chrome(current > 0),
|
|
965
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_lucide_react.ArrowLeft, { size: 24, strokeWidth: 1.5, "aria-hidden": true })
|
|
966
|
+
}
|
|
967
|
+
),
|
|
968
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: { flex: 1, minWidth: 0, overflow: "hidden" }, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1385
969
|
"div",
|
|
1386
970
|
{
|
|
1387
|
-
"data-ai-grid": String(perPage),
|
|
1388
971
|
style: {
|
|
1389
|
-
|
|
1390
|
-
|
|
1391
|
-
|
|
1392
|
-
gap: AI_TREE_TOKENS.spacing8,
|
|
1393
|
-
alignItems: "start"
|
|
972
|
+
display: "flex",
|
|
973
|
+
transform: `translateX(-${current * 100}%)`,
|
|
974
|
+
transition: "transform 0.4s ease"
|
|
1394
975
|
},
|
|
1395
|
-
children: group
|
|
1396
|
-
|
|
1397
|
-
|
|
1398
|
-
|
|
1399
|
-
|
|
1400
|
-
|
|
1401
|
-
|
|
1402
|
-
|
|
1403
|
-
|
|
1404
|
-
|
|
1405
|
-
|
|
1406
|
-
|
|
1407
|
-
|
|
1408
|
-
|
|
1409
|
-
|
|
1410
|
-
|
|
1411
|
-
|
|
1412
|
-
|
|
1413
|
-
|
|
1414
|
-
|
|
1415
|
-
|
|
1416
|
-
|
|
1417
|
-
|
|
1418
|
-
|
|
1419
|
-
|
|
1420
|
-
|
|
1421
|
-
|
|
1422
|
-
if (isMobile) {
|
|
1423
|
-
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { "data-ai-carousel": "", style: { display: "flex", flexDirection: "column", gap: AI_TREE_TOKENS.spacing6, alignItems: "center" }, children: [
|
|
1424
|
-
viewport,
|
|
1425
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: { display: "flex", gap: AI_TREE_TOKENS.spacing6, justifyContent: "center" }, children: [
|
|
1426
|
-
prevBtn,
|
|
1427
|
-
nextBtn
|
|
1428
|
-
] }),
|
|
1429
|
-
dots
|
|
1430
|
-
] });
|
|
1431
|
-
}
|
|
1432
|
-
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { "data-ai-carousel": "", style: { display: "flex", flexDirection: "column", gap: AI_TREE_TOKENS.spacing8, alignItems: "center" }, children: [
|
|
1433
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: { display: "flex", alignItems: "center", gap: AI_TREE_TOKENS.spacing6, width: "100%" }, children: [
|
|
1434
|
-
prevBtn,
|
|
1435
|
-
viewport,
|
|
1436
|
-
nextBtn
|
|
976
|
+
children: pageGroups.map((group, p) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
977
|
+
"div",
|
|
978
|
+
{
|
|
979
|
+
"data-ai-grid": String(itemsPerRow),
|
|
980
|
+
style: {
|
|
981
|
+
flex: "0 0 100%",
|
|
982
|
+
display: "grid",
|
|
983
|
+
gridTemplateColumns: `repeat(${itemsPerRow}, 1fr)`,
|
|
984
|
+
gap: AI_TREE_TOKENS.spacing8,
|
|
985
|
+
alignItems: "start"
|
|
986
|
+
},
|
|
987
|
+
children: group
|
|
988
|
+
},
|
|
989
|
+
p
|
|
990
|
+
))
|
|
991
|
+
}
|
|
992
|
+
) }),
|
|
993
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
994
|
+
"button",
|
|
995
|
+
{
|
|
996
|
+
type: "button",
|
|
997
|
+
"aria-label": "Next",
|
|
998
|
+
onClick: () => setPage((p) => Math.min(pages - 1, p + 1)),
|
|
999
|
+
style: chrome(current < pages - 1),
|
|
1000
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_lucide_react.ArrowRight, { size: 24, strokeWidth: 1.5, "aria-hidden": true })
|
|
1001
|
+
}
|
|
1002
|
+
)
|
|
1437
1003
|
] }),
|
|
1438
|
-
|
|
1004
|
+
pages > 1 && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: { display: "flex", gap: 9, justifyContent: "center" }, children: pageGroups.map((_, p) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { type: "button", "aria-label": `Page ${p + 1}`, onClick: () => setPage(p), style: dot(p === current) }, p)) })
|
|
1439
1005
|
] });
|
|
1440
1006
|
}
|
|
1441
1007
|
function CollectionBlock({ node, ctx, path }) {
|
|
@@ -1529,49 +1095,6 @@ function renderNode(node, ctx, path) {
|
|
|
1529
1095
|
switch (node.type) {
|
|
1530
1096
|
case "text":
|
|
1531
1097
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(TextBlock, { slots, ctx, path });
|
|
1532
|
-
// Layout container: arranges child blocks, contributes no content of its own. `grid` is a
|
|
1533
|
-
// nested 12-column grid the children span (a collage is 3–5 media on it, bottom-aligned so
|
|
1534
|
-
// mixed aspects read as a composition); `split` is exactly two children at a ratio; `stack`
|
|
1535
|
-
// is a column. Children render through this same dispatcher, so edit markers, media
|
|
1536
|
-
// resolution, and copy paths all work unchanged inside a group.
|
|
1537
|
-
case "group": {
|
|
1538
|
-
const layout = str(slots.layout);
|
|
1539
|
-
const gap = slots.spacing === "tight" ? AI_TREE_TOKENS.spacing3 : slots.spacing === "airy" ? AI_TREE_TOKENS.spacing8 : AI_TREE_TOKENS.spacing6;
|
|
1540
|
-
const kids = (node.children ?? []).map((child, i) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1541
|
-
"div",
|
|
1542
|
-
{
|
|
1543
|
-
style: layout === "grid" ? {
|
|
1544
|
-
gridColumn: `span ${typeof child.span === "number" ? Math.min(12, Math.max(1, child.span)) : 12}`,
|
|
1545
|
-
minWidth: 0
|
|
1546
|
-
} : { minWidth: 0 },
|
|
1547
|
-
children: renderNode(child, ctx, `${path}.c${i}`)
|
|
1548
|
-
},
|
|
1549
|
-
i
|
|
1550
|
-
));
|
|
1551
|
-
if (layout === "grid") {
|
|
1552
|
-
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1553
|
-
"div",
|
|
1554
|
-
{
|
|
1555
|
-
"data-ai-group": "grid",
|
|
1556
|
-
style: { display: "grid", gridTemplateColumns: "repeat(12, 1fr)", gap, alignItems: "end" },
|
|
1557
|
-
children: kids
|
|
1558
|
-
}
|
|
1559
|
-
);
|
|
1560
|
-
}
|
|
1561
|
-
if (layout === "split") {
|
|
1562
|
-
const ratio = str(slots.ratio);
|
|
1563
|
-
const cols = ratio === "3:5" ? "3fr 5fr" : ratio === "5:3" ? "5fr 3fr" : "1fr 1fr";
|
|
1564
|
-
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1565
|
-
"div",
|
|
1566
|
-
{
|
|
1567
|
-
"data-ai-group": "split",
|
|
1568
|
-
style: { display: "grid", gridTemplateColumns: cols, gap, alignItems: "center" },
|
|
1569
|
-
children: kids
|
|
1570
|
-
}
|
|
1571
|
-
);
|
|
1572
|
-
}
|
|
1573
|
-
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { "data-ai-group": "stack", style: { display: "flex", flexDirection: "column", gap }, children: kids });
|
|
1574
|
-
}
|
|
1575
1098
|
case "button":
|
|
1576
1099
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ButtonEl, { slots, ctx, path });
|
|
1577
1100
|
case "button-row":
|
|
@@ -1652,102 +1175,33 @@ function renderNode(node, ctx, path) {
|
|
|
1652
1175
|
}
|
|
1653
1176
|
);
|
|
1654
1177
|
}
|
|
1655
|
-
case "form":
|
|
1656
|
-
|
|
1657
|
-
"
|
|
1658
|
-
|
|
1659
|
-
|
|
1660
|
-
|
|
1661
|
-
|
|
1662
|
-
|
|
1663
|
-
|
|
1664
|
-
|
|
1665
|
-
|
|
1666
|
-
|
|
1667
|
-
|
|
1668
|
-
|
|
1669
|
-
|
|
1670
|
-
...typeStyle(AI_TREE_TOKENS.type.bodyM, ctx.brand.fonts.body)
|
|
1671
|
-
};
|
|
1672
|
-
const labelStyle = {
|
|
1673
|
-
...typeStyle(AI_TREE_TOKENS.type.bodyMBold, ctx.brand.fonts.body),
|
|
1674
|
-
color: ctx.brand.palette.dark
|
|
1675
|
-
};
|
|
1676
|
-
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1677
|
-
"form",
|
|
1678
|
-
{
|
|
1679
|
-
...formAttrs,
|
|
1680
|
-
"data-ai-form": "",
|
|
1681
|
-
style: {
|
|
1682
|
-
display: "grid",
|
|
1683
|
-
gridTemplateColumns: "repeat(2, minmax(0, 1fr))",
|
|
1684
|
-
columnGap: 64,
|
|
1685
|
-
rowGap: AI_TREE_TOKENS.spacing4
|
|
1686
|
-
},
|
|
1687
|
-
children: (node.children ?? []).map((child, i) => {
|
|
1688
|
-
if (child.type === "input") {
|
|
1689
|
-
const cs2 = child.slots ?? {};
|
|
1690
|
-
const kind = str(cs2.kind);
|
|
1691
|
-
const label = str(cs2.label);
|
|
1692
|
-
const placeholder = str(cs2.placeholder);
|
|
1693
|
-
const name = label.toLowerCase().replace(/[^a-z0-9]+/gu, "-").replace(/^-+|-+$/gu, "") || `field-${i}`;
|
|
1694
|
-
const isTextarea = kind === "textarea";
|
|
1695
|
-
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
1696
|
-
"div",
|
|
1697
|
-
{
|
|
1698
|
-
style: {
|
|
1699
|
-
display: "flex",
|
|
1700
|
-
flexDirection: "column",
|
|
1701
|
-
gap: 8,
|
|
1702
|
-
...isTextarea ? { gridColumn: "1 / -1", maxWidth: 780 } : {}
|
|
1703
|
-
},
|
|
1704
|
-
children: [
|
|
1705
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("label", { ...textAttrs(ctx, `${path}.c${i}.label`), style: labelStyle, children: label }),
|
|
1706
|
-
isTextarea ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1707
|
-
"textarea",
|
|
1708
|
-
{
|
|
1709
|
-
name,
|
|
1710
|
-
placeholder,
|
|
1711
|
-
style: { ...fieldStyle, height: 140, resize: "vertical" }
|
|
1712
|
-
}
|
|
1713
|
-
) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1714
|
-
"input",
|
|
1715
|
-
{
|
|
1716
|
-
name,
|
|
1717
|
-
type: kind === "email" ? "email" : "text",
|
|
1718
|
-
placeholder,
|
|
1719
|
-
style: { ...fieldStyle, height: 48 }
|
|
1720
|
-
}
|
|
1721
|
-
)
|
|
1722
|
-
]
|
|
1723
|
-
},
|
|
1724
|
-
i
|
|
1725
|
-
);
|
|
1726
|
-
}
|
|
1727
|
-
const cs = child.slots ?? {};
|
|
1728
|
-
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1729
|
-
"button",
|
|
1178
|
+
case "form":
|
|
1179
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: { display: "flex", flexDirection: "column", gap: AI_TREE_TOKENS.spacing4 }, children: (node.children ?? []).map((child, i) => {
|
|
1180
|
+
if (child.type === "input") {
|
|
1181
|
+
const cs = child.slots ?? {};
|
|
1182
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { children: [
|
|
1183
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1184
|
+
"div",
|
|
1185
|
+
{
|
|
1186
|
+
...textAttrs(ctx, `${path}.c${i}.label`),
|
|
1187
|
+
style: { ...typeStyle(AI_TREE_TOKENS.type.bodyMBold, ctx.brand.fonts.body), color: ctx.brand.palette.dark, marginBottom: 6 },
|
|
1188
|
+
children: str(cs.label)
|
|
1189
|
+
}
|
|
1190
|
+
),
|
|
1191
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1192
|
+
"div",
|
|
1730
1193
|
{
|
|
1731
|
-
type: "submit",
|
|
1732
1194
|
style: {
|
|
1733
|
-
|
|
1734
|
-
justifySelf: "start",
|
|
1735
|
-
border: "none",
|
|
1736
|
-
cursor: "pointer",
|
|
1737
|
-
padding: `${AI_TREE_TOKENS.spacing3}px ${AI_TREE_TOKENS.spacing6}px`,
|
|
1195
|
+
border: `1px solid ${ctx.brand.palette.accent}`,
|
|
1738
1196
|
borderRadius: AI_TREE_TOKENS.radiusButton,
|
|
1739
|
-
|
|
1740
|
-
|
|
1741
|
-
|
|
1742
|
-
|
|
1743
|
-
|
|
1744
|
-
},
|
|
1745
|
-
i
|
|
1746
|
-
);
|
|
1747
|
-
})
|
|
1197
|
+
height: cs.kind === "textarea" ? 96 : 42
|
|
1198
|
+
}
|
|
1199
|
+
}
|
|
1200
|
+
)
|
|
1201
|
+
] }, i);
|
|
1748
1202
|
}
|
|
1749
|
-
|
|
1750
|
-
|
|
1203
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ButtonEl, { slots: child.slots ?? {}, ctx, path: `${path}.c${i}` }) }, i);
|
|
1204
|
+
}) });
|
|
1751
1205
|
case "schedule-widget":
|
|
1752
1206
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1753
1207
|
"div",
|
|
@@ -1773,14 +1227,11 @@ function AiTreeRenderer({ tree, brand, resolveMedia, editKeyPrefix }) {
|
|
|
1773
1227
|
return null;
|
|
1774
1228
|
}
|
|
1775
1229
|
const resolvedBrand = brand ?? AI_DEFAULT_BRAND;
|
|
1776
|
-
const band = (tree.settings ?? {}).sectionBackground === "accent" ? accentBandContext(resolvedBrand) : null;
|
|
1777
|
-
const blockBrand = band?.brand ?? resolvedBrand;
|
|
1778
1230
|
const ctx = {
|
|
1779
|
-
brand:
|
|
1231
|
+
brand: resolvedBrand,
|
|
1780
1232
|
resolveMedia: resolveMedia ?? (() => null),
|
|
1781
|
-
cardSurface:
|
|
1782
|
-
keyFor: editKeyPrefix ? (path) => `${editKeyPrefix}.${path}` : null
|
|
1783
|
-
...band ? { buttonLabel: band.buttonLabel } : {}
|
|
1233
|
+
cardSurface: resolvedBrand.palette.light.toUpperCase() === AI_DEFAULT_BRAND.palette.light.toUpperCase() ? "#ECECEB" : `color-mix(in srgb, ${resolvedBrand.palette.light} 90%, ${resolvedBrand.palette.dark})`,
|
|
1234
|
+
keyFor: editKeyPrefix ? (path) => `${editKeyPrefix}.${path}` : null
|
|
1784
1235
|
};
|
|
1785
1236
|
const settings = tree.settings ?? {};
|
|
1786
1237
|
const pad = AI_TREE_TOKENS.sectionPadding[settings.spacing ?? "balanced"];
|
|
@@ -1788,20 +1239,6 @@ function AiTreeRenderer({ tree, brand, resolveMedia, editKeyPrefix }) {
|
|
|
1788
1239
|
const overlayAlpha = { low: 0.25, medium: 0.45, high: 0.65 }[settings.overlayIntensity ?? "medium"];
|
|
1789
1240
|
const backgroundUrl = isOverlay && settings.backgroundMedia ? ctx.resolveMedia(settings.backgroundMedia) : null;
|
|
1790
1241
|
const bgAttrs = ctx.keyFor && isOverlay && settings.backgroundMedia ? { "data-ohw-key": ctx.keyFor("settings.backgroundMedia"), "data-ohw-editable": "bg-image" } : {};
|
|
1791
|
-
const toneBackground = (() => {
|
|
1792
|
-
const { dark, primary, light } = resolvedBrand.palette;
|
|
1793
|
-
switch (settings.sectionBackground) {
|
|
1794
|
-
case "surface":
|
|
1795
|
-
return `color-mix(in srgb, ${light} 94%, ${dark})`;
|
|
1796
|
-
case "accent":
|
|
1797
|
-
return primary;
|
|
1798
|
-
case "accent-soft":
|
|
1799
|
-
return `color-mix(in srgb, ${primary} 12%, ${light})`;
|
|
1800
|
-
default:
|
|
1801
|
-
return void 0;
|
|
1802
|
-
}
|
|
1803
|
-
})();
|
|
1804
|
-
const distributed = !isOverlay && settings.textDistribution;
|
|
1805
1242
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
1806
1243
|
"section",
|
|
1807
1244
|
{
|
|
@@ -1811,15 +1248,13 @@ function AiTreeRenderer({ tree, brand, resolveMedia, editKeyPrefix }) {
|
|
|
1811
1248
|
style: {
|
|
1812
1249
|
position: "relative",
|
|
1813
1250
|
padding: `${pad}px 0`,
|
|
1814
|
-
background:
|
|
1251
|
+
background: isOverlay && !backgroundUrl ? "#DBEAFE" : void 0,
|
|
1815
1252
|
backgroundImage: backgroundUrl ? `url(${backgroundUrl})` : void 0,
|
|
1816
1253
|
backgroundSize: "cover",
|
|
1817
|
-
backgroundPosition: "center"
|
|
1818
|
-
color: settings.sectionBackground === "accent" ? blockBrand.palette.dark : void 0
|
|
1254
|
+
backgroundPosition: "center"
|
|
1819
1255
|
},
|
|
1820
1256
|
children: [
|
|
1821
1257
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("style", { children: AI_RESPONSIVE_CSS }),
|
|
1822
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("style", { children: AI_MOBILE_CSS }),
|
|
1823
1258
|
isOverlay && backgroundUrl && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: { position: "absolute", inset: 0, background: `rgba(255,255,255,${overlayAlpha})` } }),
|
|
1824
1259
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1825
1260
|
"div",
|
|
@@ -1840,24 +1275,10 @@ function AiTreeRenderer({ tree, brand, resolveMedia, editKeyPrefix }) {
|
|
|
1840
1275
|
display: "grid",
|
|
1841
1276
|
gridTemplateColumns: "repeat(12, 1fr)",
|
|
1842
1277
|
gap: AI_TREE_TOKENS.spacing6,
|
|
1843
|
-
alignItems:
|
|
1278
|
+
alignItems: settings.verticalPosition === "top" ? "start" : "center",
|
|
1844
1279
|
marginTop: r2 > 0 ? AI_TREE_TOKENS.spacing8 : 0
|
|
1845
1280
|
},
|
|
1846
|
-
children: (row.blocks ?? []).map((block, b) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1847
|
-
"div",
|
|
1848
|
-
{
|
|
1849
|
-
"data-ai-cell": "",
|
|
1850
|
-
style: {
|
|
1851
|
-
gridColumn: `span ${Math.min(12, Math.max(1, block.span))}`,
|
|
1852
|
-
minWidth: 0,
|
|
1853
|
-
// space-between: each column becomes a flex column whose content spreads over
|
|
1854
|
-
// the full row height instead of clumping at the top.
|
|
1855
|
-
...distributed === "space-between" ? { display: "flex", flexDirection: "column", justifyContent: "space-between" } : {}
|
|
1856
|
-
},
|
|
1857
|
-
children: renderNode(block, ctx, `r${r2}.b${b}`)
|
|
1858
|
-
},
|
|
1859
|
-
b
|
|
1860
|
-
))
|
|
1281
|
+
children: (row.blocks ?? []).map((block, b) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: { gridColumn: `span ${Math.min(12, Math.max(1, block.span))}`, minWidth: 0 }, children: renderNode(block, ctx, `r${r2}.b${b}`) }, b))
|
|
1861
1282
|
},
|
|
1862
1283
|
r2
|
|
1863
1284
|
))
|
|
@@ -1873,36 +1294,17 @@ var import_jsx_runtime2 = require("react/jsx-runtime");
|
|
|
1873
1294
|
var CONTAINER_ATTR = "data-ohw-ai-generated";
|
|
1874
1295
|
var REPLACED_ATTR = "data-ohw-ai-replaced-by";
|
|
1875
1296
|
var REMOVED_ATTR = "data-ohw-ai-removed";
|
|
1876
|
-
var TEMPLATE_HIDDEN_ATTR = "data-ohw-ai-template-hidden";
|
|
1877
|
-
var CHROME_SECTION_IDS = /* @__PURE__ */ new Set(["navbar", "footer"]);
|
|
1878
|
-
function readRootVar(name) {
|
|
1879
|
-
if (typeof document === "undefined") return "";
|
|
1880
|
-
return getComputedStyle(document.documentElement).getPropertyValue(name).trim();
|
|
1881
|
-
}
|
|
1882
|
-
function deriveBrandOverride() {
|
|
1883
|
-
const dark = readRootVar("--ohw-brand-dark");
|
|
1884
|
-
const primary = readRootVar("--ohw-brand-primary");
|
|
1885
|
-
const light = readRootVar("--ohw-brand-light");
|
|
1886
|
-
if (!dark || !primary || !light) return null;
|
|
1887
|
-
const accent = readRootVar("--ohw-brand-accent");
|
|
1888
|
-
const heading = readRootVar("--font-heading") || readRootVar("--font-display");
|
|
1889
|
-
const body = readRootVar("--font-body");
|
|
1890
|
-
return {
|
|
1891
|
-
palette: { dark, primary, accent: accent || dark, light },
|
|
1892
|
-
fonts: {
|
|
1893
|
-
heading: heading || AI_DEFAULT_BRAND.fonts.heading,
|
|
1894
|
-
body: body || AI_DEFAULT_BRAND.fonts.body
|
|
1895
|
-
}
|
|
1896
|
-
};
|
|
1897
|
-
}
|
|
1898
1297
|
function deriveTemplateBrand() {
|
|
1899
|
-
|
|
1900
|
-
const
|
|
1901
|
-
const
|
|
1298
|
+
if (typeof document === "undefined") return null;
|
|
1299
|
+
const cs = getComputedStyle(document.documentElement);
|
|
1300
|
+
const read = (name) => cs.getPropertyValue(name).trim();
|
|
1301
|
+
const dark = read("--color-dark");
|
|
1302
|
+
const primary = read("--color-primary");
|
|
1303
|
+
const light = read("--color-light");
|
|
1902
1304
|
if (!dark || !primary || !light) return null;
|
|
1903
|
-
const accent =
|
|
1904
|
-
const heading =
|
|
1905
|
-
const body =
|
|
1305
|
+
const accent = read("--color-accent");
|
|
1306
|
+
const heading = read("--font-heading") || read("--font-display");
|
|
1307
|
+
const body = read("--font-body");
|
|
1906
1308
|
return {
|
|
1907
1309
|
palette: { dark, primary, accent: accent || dark, light },
|
|
1908
1310
|
fonts: {
|
|
@@ -1974,24 +1376,6 @@ function syncRemovedSections(state) {
|
|
|
1974
1376
|
}
|
|
1975
1377
|
}
|
|
1976
1378
|
}
|
|
1977
|
-
function syncTemplateHidden(state, pageHasSections) {
|
|
1978
|
-
const hide = state.hideTemplate === true && pageHasSections;
|
|
1979
|
-
for (const el of Array.from(document.querySelectorAll(`[${TEMPLATE_HIDDEN_ATTR}]`))) {
|
|
1980
|
-
if (!hide) {
|
|
1981
|
-
el.style.removeProperty("display");
|
|
1982
|
-
el.removeAttribute(TEMPLATE_HIDDEN_ATTR);
|
|
1983
|
-
}
|
|
1984
|
-
}
|
|
1985
|
-
if (!hide) return;
|
|
1986
|
-
for (const el of Array.from(document.querySelectorAll("[data-ohw-section]"))) {
|
|
1987
|
-
if (el.hasAttribute(CONTAINER_ATTR)) continue;
|
|
1988
|
-
if (CHROME_SECTION_IDS.has(el.getAttribute("data-ohw-section") ?? "")) continue;
|
|
1989
|
-
if (el.parentElement?.closest("[data-ohw-section]")) continue;
|
|
1990
|
-
if (el.hasAttribute(REPLACED_ATTR) || el.hasAttribute(REMOVED_ATTR)) continue;
|
|
1991
|
-
el.style.display = "none";
|
|
1992
|
-
el.setAttribute(TEMPLATE_HIDDEN_ATTR, "");
|
|
1993
|
-
}
|
|
1994
|
-
}
|
|
1995
1379
|
function syncReplacedOriginals(state) {
|
|
1996
1380
|
for (const el of document.querySelectorAll(`[${REPLACED_ATTR}]`)) {
|
|
1997
1381
|
const byId = el.getAttribute(REPLACED_ATTR) ?? "";
|
|
@@ -2010,63 +1394,10 @@ function syncReplacedOriginals(state) {
|
|
|
2010
1394
|
}
|
|
2011
1395
|
}
|
|
2012
1396
|
}
|
|
2013
|
-
var sectionOrderIndex = /* @__PURE__ */ new Map();
|
|
2014
|
-
function setAiSectionOrder(raw, currentPath) {
|
|
2015
|
-
const next = /* @__PURE__ */ new Map();
|
|
2016
|
-
if (raw) {
|
|
2017
|
-
try {
|
|
2018
|
-
const entries = JSON.parse(raw);
|
|
2019
|
-
for (const entry of entries) {
|
|
2020
|
-
if (!entry.pagePath || entry.pagePath === currentPath) next.set(entry.instanceId, entry.order);
|
|
2021
|
-
}
|
|
2022
|
-
} catch {
|
|
2023
|
-
}
|
|
2024
|
-
}
|
|
2025
|
-
sectionOrderIndex = next;
|
|
2026
|
-
}
|
|
2027
|
-
function applyExplicitOrder(entries) {
|
|
2028
|
-
if (sectionOrderIndex.size === 0) return entries;
|
|
2029
|
-
return entries.map((entry, index) => ({ entry, index, order: sectionOrderIndex.get(entry.id) })).sort((a, b) => {
|
|
2030
|
-
if (a.order === void 0 && b.order === void 0) return a.index - b.index;
|
|
2031
|
-
if (a.order === void 0) return 1;
|
|
2032
|
-
if (b.order === void 0) return -1;
|
|
2033
|
-
return a.order - b.order;
|
|
2034
|
-
}).map((item) => item.entry);
|
|
2035
|
-
}
|
|
2036
|
-
function orderByChain(sections) {
|
|
2037
|
-
const ids = new Set(sections.map((entry) => entry.id));
|
|
2038
|
-
const after = /* @__PURE__ */ new Map();
|
|
2039
|
-
const roots = [];
|
|
2040
|
-
for (const entry of sections) {
|
|
2041
|
-
const anchor = entry.replaces ?? entry.beforeSection ?? entry.afterSection ?? null;
|
|
2042
|
-
if (anchor && ids.has(anchor)) {
|
|
2043
|
-
const bucket = after.get(anchor);
|
|
2044
|
-
if (bucket) bucket.push(entry);
|
|
2045
|
-
else after.set(anchor, [entry]);
|
|
2046
|
-
} else {
|
|
2047
|
-
roots.push(entry);
|
|
2048
|
-
}
|
|
2049
|
-
}
|
|
2050
|
-
const out = [];
|
|
2051
|
-
const seen = /* @__PURE__ */ new Set();
|
|
2052
|
-
const visit = (entry) => {
|
|
2053
|
-
if (seen.has(entry.id)) return;
|
|
2054
|
-
seen.add(entry.id);
|
|
2055
|
-
out.push(entry);
|
|
2056
|
-
for (const child of after.get(entry.id) ?? []) visit(child);
|
|
2057
|
-
};
|
|
2058
|
-
for (const root of roots) visit(root);
|
|
2059
|
-
return out.length === sections.length ? out : sections;
|
|
2060
|
-
}
|
|
2061
1397
|
function applyAiSectionsToDom(state, options) {
|
|
2062
1398
|
if (typeof document === "undefined") return;
|
|
2063
|
-
const brandOverride = deriveBrandOverride();
|
|
2064
1399
|
const templateBrand = deriveTemplateBrand();
|
|
2065
|
-
const
|
|
2066
|
-
const pagePath = window.location.pathname;
|
|
2067
|
-
const pageSections = state.sections.filter((entry) => (entry.path ?? "/") === pagePath);
|
|
2068
|
-
const activeIds = new Set(pageSections.map((entry) => entry.id));
|
|
2069
|
-
const ordered = state.hideTemplate === true ? applyExplicitOrder(orderByChain(pageSections)) : pageSections;
|
|
1400
|
+
const activeIds = new Set(state.sections.map((entry) => entry.id));
|
|
2070
1401
|
for (const [id, section] of mounted) {
|
|
2071
1402
|
if (!activeIds.has(id)) {
|
|
2072
1403
|
section.root.unmount();
|
|
@@ -2074,8 +1405,8 @@ function applyAiSectionsToDom(state, options) {
|
|
|
2074
1405
|
mounted.delete(id);
|
|
2075
1406
|
}
|
|
2076
1407
|
}
|
|
2077
|
-
for (const entry of
|
|
2078
|
-
const serialized = JSON.stringify(entry)
|
|
1408
|
+
for (const entry of state.sections) {
|
|
1409
|
+
const serialized = JSON.stringify(entry);
|
|
2079
1410
|
const existing = mounted.get(entry.id);
|
|
2080
1411
|
if (existing && existing.serialized === serialized && existing.container.isConnected) {
|
|
2081
1412
|
continue;
|
|
@@ -2100,7 +1431,7 @@ function applyAiSectionsToDom(state, options) {
|
|
|
2100
1431
|
AiTreeRenderer,
|
|
2101
1432
|
{
|
|
2102
1433
|
tree: entry.tree,
|
|
2103
|
-
brand:
|
|
1434
|
+
brand: entry.brand ?? options?.brand ?? templateBrand ?? void 0,
|
|
2104
1435
|
resolveMedia,
|
|
2105
1436
|
editKeyPrefix: `ai.${entry.id}`
|
|
2106
1437
|
}
|
|
@@ -2109,20 +1440,8 @@ function applyAiSectionsToDom(state, options) {
|
|
|
2109
1440
|
});
|
|
2110
1441
|
mounted.set(entry.id, { root, container, serialized });
|
|
2111
1442
|
}
|
|
2112
|
-
if (state.hideTemplate === true) {
|
|
2113
|
-
let prev = null;
|
|
2114
|
-
for (const entry of ordered) {
|
|
2115
|
-
const el = mounted.get(entry.id)?.container;
|
|
2116
|
-
if (!el) continue;
|
|
2117
|
-
if (prev && !(prev.compareDocumentPosition(el) & Node.DOCUMENT_POSITION_FOLLOWING)) {
|
|
2118
|
-
prev.insertAdjacentElement("afterend", el);
|
|
2119
|
-
}
|
|
2120
|
-
prev = el;
|
|
2121
|
-
}
|
|
2122
|
-
}
|
|
2123
1443
|
syncReplacedOriginals(state);
|
|
2124
1444
|
syncRemovedSections(state);
|
|
2125
|
-
syncTemplateHidden(state, pageSections.length > 0);
|
|
2126
1445
|
}
|
|
2127
1446
|
|
|
2128
1447
|
// src/useLinkHrefGuardian.ts
|
|
@@ -2729,7 +2048,7 @@ function SchedulingWidget({ notifyOnConnect = false, initialScheduleId, insertAf
|
|
|
2729
2048
|
const autoId = (0, import_react5.useId)();
|
|
2730
2049
|
const insertAfter = insertAfterProp ?? autoId;
|
|
2731
2050
|
const [schedule, setSchedule] = (0, import_react5.useState)(null);
|
|
2732
|
-
const [loading, setLoading] = (0, import_react5.useState)(
|
|
2051
|
+
const [loading, setLoading] = (0, import_react5.useState)(true);
|
|
2733
2052
|
const [inEditor, setInEditor] = (0, import_react5.useState)(false);
|
|
2734
2053
|
const [isHovered, setIsHovered] = (0, import_react5.useState)(false);
|
|
2735
2054
|
const [modalState, setModalState] = (0, import_react5.useState)(null);
|
|
@@ -2903,10 +2222,8 @@ function SchedulingWidget({ notifyOnConnect = false, initialScheduleId, insertAf
|
|
|
2903
2222
|
"*"
|
|
2904
2223
|
);
|
|
2905
2224
|
};
|
|
2225
|
+
if (!inEditor && !loading && !schedule) return null;
|
|
2906
2226
|
const sectionId = `scheduling-${insertAfter}`;
|
|
2907
|
-
if (!inEditor && !loading && !schedule) {
|
|
2908
|
-
return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("section", { "data-ohw-section": sectionId, "data-ohw-scheduling-anchor": insertAfter, style: { display: "none" } });
|
|
2909
|
-
}
|
|
2910
2227
|
return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
|
|
2911
2228
|
"section",
|
|
2912
2229
|
{
|
|
@@ -7823,17 +7140,13 @@ function MediaOverlay({
|
|
|
7823
7140
|
hover,
|
|
7824
7141
|
isUploading,
|
|
7825
7142
|
fadingOut = false,
|
|
7826
|
-
selected = false,
|
|
7827
|
-
hovered = false,
|
|
7828
7143
|
onFadeOutComplete,
|
|
7829
7144
|
onReplace,
|
|
7830
|
-
onSelect,
|
|
7831
7145
|
onVideoSettingsChange
|
|
7832
7146
|
}) {
|
|
7833
7147
|
const { rect } = hover;
|
|
7834
7148
|
const skeletonRef = React8.useRef(null);
|
|
7835
7149
|
const isVideo = hover.elementType === "video";
|
|
7836
|
-
const showChrome = !selected || hovered;
|
|
7837
7150
|
const autoplay = hover.videoAutoplay ?? true;
|
|
7838
7151
|
const muted = hover.videoMuted ?? true;
|
|
7839
7152
|
const probeRef = React8.useRef(null);
|
|
@@ -7847,7 +7160,6 @@ function MediaOverlay({
|
|
|
7847
7160
|
(prev) => prev && prev.fullWidth === width && prev.height === height ? prev : { fullWidth: width, height }
|
|
7848
7161
|
);
|
|
7849
7162
|
}, [isVideo]);
|
|
7850
|
-
const replaceLabel = isVideo ? "Replace video" : hover.elementType === "bg-image" ? "Replace background" : "Replace image";
|
|
7851
7163
|
const replaceMode = buttonSize ? replaceButtonMode({ width: rect.width, height: rect.height }, buttonSize) : "none";
|
|
7852
7164
|
const box = {
|
|
7853
7165
|
position: "fixed",
|
|
@@ -7881,7 +7193,7 @@ function MediaOverlay({
|
|
|
7881
7193
|
}
|
|
7882
7194
|
);
|
|
7883
7195
|
}
|
|
7884
|
-
const settingsBar = isVideo && !hover.isDragOver
|
|
7196
|
+
const settingsBar = isVideo && !hover.isDragOver ? /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(
|
|
7885
7197
|
"div",
|
|
7886
7198
|
{
|
|
7887
7199
|
"data-ohw-bridge": "",
|
|
@@ -7951,12 +7263,10 @@ function MediaOverlay({
|
|
|
7951
7263
|
// in-document, pointer-events does it natively. The button below opts back in, so
|
|
7952
7264
|
// Replace still works.
|
|
7953
7265
|
pointerEvents: hover.hasTextOverlap ? "none" : "auto",
|
|
7954
|
-
|
|
7955
|
-
|
|
7956
|
-
boxShadow: selected ? "inset 0 0 0 2px var(--color-primary)" : "inset 0 0 0 1.5px var(--color-primary)",
|
|
7957
|
-
background: selected ? "transparent" : "color-mix(in srgb, var(--color-primary) 20%, transparent)"
|
|
7266
|
+
boxShadow: "inset 0 0 0 1.5px var(--color-primary)",
|
|
7267
|
+
background: "color-mix(in srgb, var(--color-primary) 20%, transparent)"
|
|
7958
7268
|
},
|
|
7959
|
-
onClick: () =>
|
|
7269
|
+
onClick: () => onReplace(hover.key),
|
|
7960
7270
|
children: [
|
|
7961
7271
|
/* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(
|
|
7962
7272
|
Button,
|
|
@@ -7977,17 +7287,17 @@ function MediaOverlay({
|
|
|
7977
7287
|
},
|
|
7978
7288
|
children: [
|
|
7979
7289
|
isVideo ? /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(import_lucide_react5.Film, { size: 14 }) : /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(import_lucide_react5.ImageIcon, { size: 14 }),
|
|
7980
|
-
|
|
7290
|
+
isVideo ? "Replace video" : "Replace image"
|
|
7981
7291
|
]
|
|
7982
7292
|
}
|
|
7983
7293
|
),
|
|
7984
|
-
|
|
7294
|
+
replaceMode === "none" ? null : /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(
|
|
7985
7295
|
Button,
|
|
7986
7296
|
{
|
|
7987
7297
|
"data-ohw-media-overlay": "",
|
|
7988
7298
|
variant: "outline",
|
|
7989
7299
|
size: "sm",
|
|
7990
|
-
"aria-label":
|
|
7300
|
+
"aria-label": isVideo ? "Replace video" : "Replace image",
|
|
7991
7301
|
className: "gap-1.5 cursor-pointer hover:bg-background",
|
|
7992
7302
|
style: {
|
|
7993
7303
|
...OVERLAY_BUTTON_STYLE,
|
|
@@ -8010,7 +7320,7 @@ function MediaOverlay({
|
|
|
8010
7320
|
},
|
|
8011
7321
|
children: [
|
|
8012
7322
|
isVideo ? /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(import_lucide_react5.Film, { size: 14 }) : /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(import_lucide_react5.ImageIcon, { size: 14 }),
|
|
8013
|
-
replaceMode === "full" ?
|
|
7323
|
+
replaceMode === "full" ? isVideo ? "Replace video" : "Replace image" : null
|
|
8014
7324
|
]
|
|
8015
7325
|
}
|
|
8016
7326
|
)
|
|
@@ -8094,8 +7404,6 @@ function parseSectionsFromRoot(root) {
|
|
|
8094
7404
|
const id = el.getAttribute("data-ohw-section") ?? "";
|
|
8095
7405
|
if (!id || seen.has(id) || LINK_PICKER_EXCLUDED_IDS.has(id)) continue;
|
|
8096
7406
|
if (el.parentElement?.closest("[data-ohw-section]")) continue;
|
|
8097
|
-
if (el.hasAttribute("data-ohw-ai-template-hidden") || el.hasAttribute("data-ohw-ai-removed") || el.hasAttribute("data-ohw-ai-replaced-by"))
|
|
8098
|
-
continue;
|
|
8099
7407
|
seen.add(id);
|
|
8100
7408
|
const label = el.getAttribute("data-ohw-section-label") ?? titleCaseSectionId(id);
|
|
8101
7409
|
sections.push({ id, label });
|
|
@@ -8125,10 +7433,6 @@ function topLevelSections() {
|
|
|
8125
7433
|
function instanceIdOf(el) {
|
|
8126
7434
|
return el.dataset.ohwInstance ?? el.dataset.ohwSection ?? "";
|
|
8127
7435
|
}
|
|
8128
|
-
function findByInstanceId(instanceId) {
|
|
8129
|
-
const escapedId = CSS.escape(instanceId);
|
|
8130
|
-
return document.querySelector(`[data-ohw-instance="${escapedId}"]`) ?? document.querySelector(`[data-ohw-section="${escapedId}"]:not([data-ohw-instance])`);
|
|
8131
|
-
}
|
|
8132
7436
|
function planSectionMove(instanceId, targetIndex, currentPath) {
|
|
8133
7437
|
const sections = topLevelSections();
|
|
8134
7438
|
const index = sections.findIndex((el) => instanceIdOf(el) === instanceId);
|
|
@@ -8164,7 +7468,7 @@ function syncRemovedFlags(entries) {
|
|
|
8164
7468
|
}
|
|
8165
7469
|
});
|
|
8166
7470
|
for (const id of removedIds) {
|
|
8167
|
-
const el =
|
|
7471
|
+
const el = document.querySelector(`[data-ohw-instance="${CSS.escape(id)}"]`);
|
|
8168
7472
|
if (el) {
|
|
8169
7473
|
el.style.display = "none";
|
|
8170
7474
|
el.setAttribute(REMOVED_ATTR2, "");
|
|
@@ -8192,7 +7496,9 @@ function applyPersistedOrder(entries) {
|
|
|
8192
7496
|
}
|
|
8193
7497
|
}
|
|
8194
7498
|
function setSectionRemoved(instanceId, currentPath, existingEntries, removed) {
|
|
8195
|
-
|
|
7499
|
+
const escapedId = CSS.escape(instanceId);
|
|
7500
|
+
if (!document.querySelector(`[data-ohw-instance="${escapedId}"]`) && !document.querySelector(`[data-ohw-section="${escapedId}"]:not([data-ohw-instance])`))
|
|
7501
|
+
return null;
|
|
8196
7502
|
const byId = new Map(existingEntries.map((e) => [e.instanceId, e]));
|
|
8197
7503
|
const allSections = Array.from(document.querySelectorAll("[data-ohw-section]")).filter(
|
|
8198
7504
|
(el) => !el.parentElement?.closest("[data-ohw-section]") && !isChromeSection(el)
|
|
@@ -8381,7 +7687,6 @@ function AiSectionOverlay({
|
|
|
8381
7687
|
}) {
|
|
8382
7688
|
const [selectedId, setSelectedId] = (0, import_react8.useState)(null);
|
|
8383
7689
|
const [reviewId, setReviewId] = (0, import_react8.useState)(null);
|
|
8384
|
-
const [reviewButtonsHidden, setReviewButtonsHidden] = (0, import_react8.useState)(false);
|
|
8385
7690
|
const reviewIdRef = (0, import_react8.useRef)(null);
|
|
8386
7691
|
reviewIdRef.current = reviewId;
|
|
8387
7692
|
const selectedIdRef = (0, import_react8.useRef)(null);
|
|
@@ -8443,7 +7748,6 @@ function AiSectionOverlay({
|
|
|
8443
7748
|
}
|
|
8444
7749
|
const found = readRect(sectionId) != null;
|
|
8445
7750
|
setReviewId(found ? sectionId : null);
|
|
8446
|
-
setReviewButtonsHidden(e.data.hideButtons === true);
|
|
8447
7751
|
postToParent2({ type: "ow:ai-review-started", sectionId, found });
|
|
8448
7752
|
if (found) {
|
|
8449
7753
|
document.querySelector(`[data-ohw-instance="${CSS.escape(sectionId)}"]`)?.scrollIntoView({ behavior: "smooth", block: "nearest" });
|
|
@@ -8571,16 +7875,13 @@ function AiSectionOverlay({
|
|
|
8571
7875
|
border: `2px solid ${PRIMARY2}`,
|
|
8572
7876
|
borderRadius: edgeAwareRadius(reviewRect),
|
|
8573
7877
|
zIndex: 2147483200,
|
|
8574
|
-
// The veil itself: swallows clicks so the section stays locked until decided.
|
|
8575
|
-
// stopPropagation only guards the bubble phase; the bridge's capture-phase click
|
|
8576
|
-
// handlers additionally bail on `[data-ohw-ai-review]`, without which a click on
|
|
8577
|
-
// Accept/Discard resolves to the media beneath and opens the file picker.
|
|
7878
|
+
// The veil itself: swallows clicks so the section stays locked until decided.
|
|
8578
7879
|
background: "rgba(8, 133, 254, 0.04)",
|
|
8579
7880
|
pointerEvents: "auto",
|
|
8580
7881
|
cursor: "default"
|
|
8581
7882
|
},
|
|
8582
7883
|
onClick: (e) => e.stopPropagation(),
|
|
8583
|
-
children:
|
|
7884
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(
|
|
8584
7885
|
"div",
|
|
8585
7886
|
{
|
|
8586
7887
|
style: {
|
|
@@ -11147,13 +10448,8 @@ function referenceBox(slot) {
|
|
|
11147
10448
|
const neighbour = row ? Array.from(row.querySelectorAll('[data-ohw-editable="icon"]')).find(
|
|
11148
10449
|
(el) => el !== slot && !el.hasAttribute("data-ohw-social-icon-placeholder")
|
|
11149
10450
|
) : null;
|
|
11150
|
-
|
|
11151
|
-
|
|
11152
|
-
if (box2?.width && box2.height) return box2;
|
|
11153
|
-
}
|
|
11154
|
-
const own = slot.getBoundingClientRect();
|
|
11155
|
-
if (own.width && own.height) return own;
|
|
11156
|
-
const box = slot.querySelector(GLYPH_SELECTOR)?.getBoundingClientRect() ?? null;
|
|
10451
|
+
const source = (neighbour ?? slot).querySelector(GLYPH_SELECTOR);
|
|
10452
|
+
const box = source?.getBoundingClientRect() ?? null;
|
|
11157
10453
|
return box?.width && box.height ? box : null;
|
|
11158
10454
|
}
|
|
11159
10455
|
function iconMarkupSizedFor(slot, markup) {
|
|
@@ -12954,7 +12250,6 @@ function readLogoSizeState(content, placement) {
|
|
|
12954
12250
|
function getLogoElement(el) {
|
|
12955
12251
|
const marked = el.closest('[data-ohw-role="logo"], [data-ohw-logo]');
|
|
12956
12252
|
if (marked) return marked;
|
|
12957
|
-
if (el.closest('[data-ohw-editable="icon"]')) return null;
|
|
12958
12253
|
const root = el.closest("nav, [data-ohw-nav-root], footer");
|
|
12959
12254
|
if (!root) return null;
|
|
12960
12255
|
const anchor = el.closest("a");
|
|
@@ -14023,7 +13318,6 @@ function useSectionDrag({
|
|
|
14023
13318
|
}
|
|
14024
13319
|
const orderJson = JSON.stringify(entries);
|
|
14025
13320
|
editContentRef.current = { ...editContentRef.current, [SECTION_ORDER_KEY]: orderJson };
|
|
14026
|
-
setAiSectionOrder(orderJson, window.location.pathname);
|
|
14027
13321
|
postToParentRef.current({ type: "ow:change", nodes: [{ key: SECTION_ORDER_KEY, text: orderJson }] });
|
|
14028
13322
|
applyPersistedOrder(entries);
|
|
14029
13323
|
clearSectionDragVisuals();
|
|
@@ -14883,10 +14177,21 @@ function parseSchedulingInsertAfter(insertAfter) {
|
|
|
14883
14177
|
insertBefore: insertAfter.slice(idx + INSERT_BEFORE_MARKER.length)
|
|
14884
14178
|
};
|
|
14885
14179
|
}
|
|
14886
|
-
function
|
|
14887
|
-
|
|
14888
|
-
const
|
|
14889
|
-
|
|
14180
|
+
function resolveSchedulingInsert(insertAfter, explicitInsertBefore) {
|
|
14181
|
+
const parsed = parseSchedulingInsertAfter(insertAfter);
|
|
14182
|
+
const insertBefore = explicitInsertBefore ?? parsed.insertBefore;
|
|
14183
|
+
const effectiveInsertAfter = insertBefore && parsed.insertBefore === null ? `${insertAfter}${INSERT_BEFORE_MARKER}${insertBefore}` : insertAfter;
|
|
14184
|
+
return { effectiveInsertAfter, insertBefore };
|
|
14185
|
+
}
|
|
14186
|
+
function getSchedulingMountPoint(insertAfter) {
|
|
14187
|
+
const { anchor } = parseSchedulingInsertAfter(insertAfter);
|
|
14188
|
+
let anchorEl = document.querySelector(`[data-ohw-section="${anchor}"]`);
|
|
14189
|
+
if (!anchorEl && anchor === "scheduling") {
|
|
14190
|
+
const widgets = Array.from(document.querySelectorAll('[data-ohw-section^="scheduling-"]'));
|
|
14191
|
+
anchorEl = widgets.at(-1) ?? null;
|
|
14192
|
+
}
|
|
14193
|
+
if (!anchorEl) return null;
|
|
14194
|
+
return anchorEl.closest('[data-ohw-section-container="scheduling"]') ?? anchorEl;
|
|
14890
14195
|
}
|
|
14891
14196
|
function schedulingMountDepth(insertAfter) {
|
|
14892
14197
|
if (!insertAfter.includes(INSERT_BEFORE_MARKER)) return 0;
|
|
@@ -14903,7 +14208,8 @@ function getPageSchedulingEntries(raw) {
|
|
|
14903
14208
|
}
|
|
14904
14209
|
}
|
|
14905
14210
|
function isSchedulingWidgetMissing(entry) {
|
|
14906
|
-
|
|
14211
|
+
const { effectiveInsertAfter } = resolveSchedulingInsert(entry.insertAfter);
|
|
14212
|
+
return !document.querySelector(`[data-ohw-section="${schedulingSectionId(effectiveInsertAfter)}"]`);
|
|
14907
14213
|
}
|
|
14908
14214
|
function hasMissingSchedulingWidgets(entries) {
|
|
14909
14215
|
return entries.some(isSchedulingWidgetMissing);
|
|
@@ -14933,17 +14239,16 @@ function initSectionsFromContent(content, removeExisting = false) {
|
|
|
14933
14239
|
} catch {
|
|
14934
14240
|
}
|
|
14935
14241
|
}
|
|
14936
|
-
function mountSchedulingWidget(
|
|
14937
|
-
const
|
|
14938
|
-
const sectionId = schedulingSectionId(
|
|
14242
|
+
function mountSchedulingWidget(insertAfter, notifyOnConnect = false, scheduleId, explicitInsertBefore) {
|
|
14243
|
+
const { effectiveInsertAfter, insertBefore } = resolveSchedulingInsert(insertAfter, explicitInsertBefore);
|
|
14244
|
+
const sectionId = schedulingSectionId(effectiveInsertAfter);
|
|
14939
14245
|
if (document.querySelector(`[data-ohw-section="${sectionId}"]`)) return false;
|
|
14940
|
-
const
|
|
14941
|
-
if (!
|
|
14942
|
-
const mountPoint = anchorEl.closest('[data-ohw-section-container="scheduling"]') ?? anchorEl;
|
|
14246
|
+
const mountPoint = getSchedulingMountPoint(effectiveInsertAfter);
|
|
14247
|
+
if (!mountPoint) return false;
|
|
14943
14248
|
const container = document.createElement("div");
|
|
14944
14249
|
container.dataset.ohwSectionContainer = "scheduling";
|
|
14945
|
-
if (
|
|
14946
|
-
const beforeAnchor = document.querySelector(`[data-ohw-section="${
|
|
14250
|
+
if (insertBefore) {
|
|
14251
|
+
const beforeAnchor = document.querySelector(`[data-ohw-section="${insertBefore}"]`);
|
|
14947
14252
|
const beforePoint = beforeAnchor?.closest('[data-ohw-section-container="scheduling"]') ?? beforeAnchor;
|
|
14948
14253
|
if (!beforePoint) return false;
|
|
14949
14254
|
beforePoint.insertAdjacentElement("beforebegin", container);
|
|
@@ -14954,25 +14259,19 @@ function mountSchedulingWidget(anchorId, notifyOnConnect = false, scheduleId, be
|
|
|
14954
14259
|
}
|
|
14955
14260
|
tail.insertAdjacentElement("afterend", container);
|
|
14956
14261
|
}
|
|
14957
|
-
|
|
14958
|
-
|
|
14959
|
-
|
|
14960
|
-
|
|
14961
|
-
|
|
14962
|
-
|
|
14963
|
-
|
|
14964
|
-
|
|
14965
|
-
|
|
14966
|
-
|
|
14967
|
-
|
|
14968
|
-
|
|
14969
|
-
|
|
14970
|
-
});
|
|
14971
|
-
} catch (err) {
|
|
14972
|
-
console.error("[ow:scheduling] render threw", err);
|
|
14973
|
-
container.remove();
|
|
14974
|
-
return false;
|
|
14975
|
-
}
|
|
14262
|
+
const root = (0, import_client2.createRoot)(container);
|
|
14263
|
+
(0, import_react_dom3.flushSync)(() => {
|
|
14264
|
+
root.render(
|
|
14265
|
+
/* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
|
|
14266
|
+
SchedulingWidget,
|
|
14267
|
+
{
|
|
14268
|
+
notifyOnConnect,
|
|
14269
|
+
initialScheduleId: scheduleId,
|
|
14270
|
+
insertAfter: effectiveInsertAfter
|
|
14271
|
+
}
|
|
14272
|
+
)
|
|
14273
|
+
);
|
|
14274
|
+
});
|
|
14976
14275
|
const tracker = getSectionsTracker();
|
|
14977
14276
|
let sections = [];
|
|
14978
14277
|
try {
|
|
@@ -14980,12 +14279,10 @@ function mountSchedulingWidget(anchorId, notifyOnConnect = false, scheduleId, be
|
|
|
14980
14279
|
} catch {
|
|
14981
14280
|
}
|
|
14982
14281
|
const inEditor = typeof window !== "undefined" && window.self !== window.top;
|
|
14983
|
-
if (inEditor && !sections.find((s) => s.type === "scheduling" && s.insertAfter ===
|
|
14282
|
+
if (inEditor && !sections.find((s) => s.type === "scheduling" && s.insertAfter === effectiveInsertAfter)) {
|
|
14984
14283
|
sections.push({
|
|
14985
14284
|
type: "scheduling",
|
|
14986
|
-
insertAfter:
|
|
14987
|
-
anchorId,
|
|
14988
|
-
beforeId: beforeId ?? null,
|
|
14285
|
+
insertAfter: effectiveInsertAfter,
|
|
14989
14286
|
pagePath: window.location.pathname,
|
|
14990
14287
|
...scheduleId ? { scheduleId } : {}
|
|
14991
14288
|
});
|
|
@@ -14999,8 +14296,7 @@ function mountSchedulingEntries(entries, notifyOnConnect = false) {
|
|
|
14999
14296
|
for (let i = pending.length - 1; i >= 0; i--) {
|
|
15000
14297
|
const entry = pending[i];
|
|
15001
14298
|
const shouldNotify = typeof notifyOnConnect === "function" ? notifyOnConnect(entry) : notifyOnConnect;
|
|
15002
|
-
|
|
15003
|
-
if (mountSchedulingWidget(anchorId, shouldNotify, entry.scheduleId ?? null, beforeId, entry.insertAfter)) {
|
|
14299
|
+
if (mountSchedulingWidget(entry.insertAfter, shouldNotify, entry.scheduleId)) {
|
|
15004
14300
|
pending.splice(i, 1);
|
|
15005
14301
|
}
|
|
15006
14302
|
}
|
|
@@ -15158,11 +14454,6 @@ function applyLinkByKey(key, val) {
|
|
|
15158
14454
|
hrefAnchors.forEach((el) => applyLinkHref(el, val));
|
|
15159
14455
|
}
|
|
15160
14456
|
}
|
|
15161
|
-
function isInsideLinkEditor(target) {
|
|
15162
|
-
return Boolean(
|
|
15163
|
-
target.closest("[data-ohw-link-popover-root]") || target.closest("[data-ohw-link-modal-root]") || target.closest("[data-ohw-link-page-dropdown]") || target.closest("[data-ohw-section-picker]") || target.closest("[data-ohw-navbar-container-chrome]") || target.closest("[data-ohw-navbar-add-button]") || target.closest("[data-ohw-footer-container-chrome]") || target.closest("[data-ohw-footer-add-button]") || target.closest("[data-ohw-more-menu]") || target.closest('[data-slot="dropdown-menu-content"]') || target.closest('[data-slot="popover-content"]') || target.closest('[data-slot="dialog-content"]') || target.closest('[data-slot="dialog-overlay"]')
|
|
15164
|
-
);
|
|
15165
|
-
}
|
|
15166
14457
|
function isInsideFloatingPanel(target) {
|
|
15167
14458
|
return Boolean(target.closest("[data-ohw-floating-panel]"));
|
|
15168
14459
|
}
|
|
@@ -15170,6 +14461,11 @@ function isPointOverFloatingPanel(clientX, clientY) {
|
|
|
15170
14461
|
const el = document.elementFromPoint(clientX, clientY);
|
|
15171
14462
|
return Boolean(el instanceof Element && el.closest("[data-ohw-floating-panel]"));
|
|
15172
14463
|
}
|
|
14464
|
+
function isInsideLinkEditor(target) {
|
|
14465
|
+
return Boolean(
|
|
14466
|
+
target.closest("[data-ohw-link-popover-root]") || target.closest("[data-ohw-link-modal-root]") || target.closest("[data-ohw-link-page-dropdown]") || target.closest("[data-ohw-section-picker]") || target.closest("[data-ohw-navbar-container-chrome]") || target.closest("[data-ohw-navbar-add-button]") || target.closest("[data-ohw-footer-container-chrome]") || target.closest("[data-ohw-footer-add-button]") || target.closest("[data-ohw-more-menu]") || target.closest('[data-slot="dropdown-menu-content"]') || target.closest('[data-slot="popover-content"]') || target.closest('[data-slot="dialog-content"]') || target.closest('[data-slot="dialog-overlay"]')
|
|
14467
|
+
);
|
|
14468
|
+
}
|
|
15173
14469
|
function getHrefKeyFromElement(el) {
|
|
15174
14470
|
if (!el) return null;
|
|
15175
14471
|
const anchor = el.closest("[data-ohw-href-key]");
|
|
@@ -15428,7 +14724,7 @@ function getNavigationSelectionParent(el) {
|
|
|
15428
14724
|
if (!isFooterLinksContainer(el) && (el.hasAttribute("data-ohw-footer-col") || el.hasAttribute("data-ohw-footer-column") || isInferredFooterGroup2(el))) {
|
|
15429
14725
|
return getFooterLinksContainer();
|
|
15430
14726
|
}
|
|
15431
|
-
if (el.hasAttribute("data-ohw-nav-container") || el.hasAttribute("data-ohw-nav-drawer") ||
|
|
14727
|
+
if (el.hasAttribute("data-ohw-nav-container") || el.hasAttribute("data-ohw-nav-drawer") || isFooterLinksContainer(el)) {
|
|
15432
14728
|
return getNavigationRoot(el);
|
|
15433
14729
|
}
|
|
15434
14730
|
return null;
|
|
@@ -15643,6 +14939,7 @@ var ICONS = {
|
|
|
15643
14939
|
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"/>',
|
|
15644
14940
|
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"/>'
|
|
15645
14941
|
};
|
|
14942
|
+
var HEIGHT_SETTLE_DELAYS = [150, 400, 800];
|
|
15646
14943
|
var SELECTION_CHROME_GAP2 = 4;
|
|
15647
14944
|
var TOOLBAR_STROKE_GAP2 = 4;
|
|
15648
14945
|
var TOOLBAR_OFFSET_FROM_ELEMENT = SELECTION_CHROME_GAP2 + TOOLBAR_STROKE_GAP2;
|
|
@@ -16022,7 +15319,6 @@ function StateToggle({
|
|
|
16022
15319
|
);
|
|
16023
15320
|
}
|
|
16024
15321
|
var contentCache = /* @__PURE__ */ new Map();
|
|
16025
|
-
var fetchedContentPaths = /* @__PURE__ */ new Set();
|
|
16026
15322
|
var OHW_LOADER_STYLE = {
|
|
16027
15323
|
position: "fixed",
|
|
16028
15324
|
inset: 0,
|
|
@@ -16141,70 +15437,6 @@ function OhhwellsBridge() {
|
|
|
16141
15437
|
const hoveredImageHasTextOverlapRef = (0, import_react17.useRef)(false);
|
|
16142
15438
|
const dragOverElRef = (0, import_react17.useRef)(null);
|
|
16143
15439
|
const [mediaHover, setMediaHover] = (0, import_react17.useState)(null);
|
|
16144
|
-
const [selectedMedia, setSelectedMedia] = (0, import_react17.useState)(null);
|
|
16145
|
-
const selectedMediaElRef = (0, import_react17.useRef)(null);
|
|
16146
|
-
const clearMediaSelection = (0, import_react17.useCallback)(() => {
|
|
16147
|
-
const prev = selectedMediaElRef.current;
|
|
16148
|
-
selectedMediaElRef.current = null;
|
|
16149
|
-
setSelectedMedia(null);
|
|
16150
|
-
const sectionEl = prev?.closest("[data-ohw-section]") ?? null;
|
|
16151
|
-
if (sectionEl) {
|
|
16152
|
-
postToParentRef.current({
|
|
16153
|
-
type: "ow:section-selected",
|
|
16154
|
-
sectionId: sectionEl.dataset.ohwSection ?? null,
|
|
16155
|
-
sectionLabel: sectionEl.dataset.ohwSectionLabel ?? titleCaseSectionId(sectionEl.dataset.ohwSection ?? ""),
|
|
16156
|
-
key: null
|
|
16157
|
-
});
|
|
16158
|
-
}
|
|
16159
|
-
}, []);
|
|
16160
|
-
const clearMediaSelectionRef = (0, import_react17.useRef)(clearMediaSelection);
|
|
16161
|
-
clearMediaSelectionRef.current = clearMediaSelection;
|
|
16162
|
-
const selectMediaElement = (0, import_react17.useCallback)((el) => {
|
|
16163
|
-
const r2 = el.getBoundingClientRect();
|
|
16164
|
-
const video = el.dataset.ohwEditable === "video" ? el.querySelector("video") : null;
|
|
16165
|
-
selectedMediaElRef.current = el;
|
|
16166
|
-
setSelectedMedia({
|
|
16167
|
-
key: el.dataset.ohwKey ?? "",
|
|
16168
|
-
rect: { top: r2.top, left: r2.left, width: r2.width, height: r2.height },
|
|
16169
|
-
elementType: el.dataset.ohwEditable ?? "image",
|
|
16170
|
-
hasTextOverlap: false,
|
|
16171
|
-
isDragOver: false,
|
|
16172
|
-
...video ? { videoAutoplay: video.autoplay, videoMuted: video.muted } : {}
|
|
16173
|
-
});
|
|
16174
|
-
const sectionEl = el.closest("[data-ohw-section]");
|
|
16175
|
-
aiSectionApiRef.current?.selectFromElement(el, { report: false });
|
|
16176
|
-
postToParentRef.current({
|
|
16177
|
-
type: "ow:section-selected",
|
|
16178
|
-
sectionId: sectionEl?.dataset.ohwSection ?? null,
|
|
16179
|
-
sectionLabel: sectionEl ? sectionEl.dataset.ohwSectionLabel ?? titleCaseSectionId(sectionEl.dataset.ohwSection ?? "") : null,
|
|
16180
|
-
key: el.dataset.ohwKey ?? null,
|
|
16181
|
-
// Display name for the pill — the raw key prettifies into fragments ("Img"); the
|
|
16182
|
-
// bridge knows what the node IS, so it names it.
|
|
16183
|
-
keyLabel: el.dataset.ohwEditable === "video" ? "Video" : el.dataset.ohwEditable === "bg-image" ? "Background" : "Image"
|
|
16184
|
-
});
|
|
16185
|
-
}, []);
|
|
16186
|
-
const selectMediaElementRef = (0, import_react17.useRef)(selectMediaElement);
|
|
16187
|
-
selectMediaElementRef.current = selectMediaElement;
|
|
16188
|
-
(0, import_react17.useEffect)(() => {
|
|
16189
|
-
if (!selectedMedia) return;
|
|
16190
|
-
const update = () => {
|
|
16191
|
-
const el = selectedMediaElRef.current;
|
|
16192
|
-
if (!el || !el.isConnected) {
|
|
16193
|
-
clearMediaSelection();
|
|
16194
|
-
return;
|
|
16195
|
-
}
|
|
16196
|
-
const r2 = el.getBoundingClientRect();
|
|
16197
|
-
setSelectedMedia(
|
|
16198
|
-
(prev) => prev ? { ...prev, rect: { top: r2.top, left: r2.left, width: r2.width, height: r2.height } } : prev
|
|
16199
|
-
);
|
|
16200
|
-
};
|
|
16201
|
-
window.addEventListener("scroll", update, true);
|
|
16202
|
-
window.addEventListener("resize", update);
|
|
16203
|
-
return () => {
|
|
16204
|
-
window.removeEventListener("scroll", update, true);
|
|
16205
|
-
window.removeEventListener("resize", update);
|
|
16206
|
-
};
|
|
16207
|
-
}, [selectedMedia !== null]);
|
|
16208
15440
|
const [carouselHover, setCarouselHover] = (0, import_react17.useState)(null);
|
|
16209
15441
|
const [uploadingRects, setUploadingRects] = (0, import_react17.useState)({});
|
|
16210
15442
|
const hoveredGapRef = (0, import_react17.useRef)(null);
|
|
@@ -16467,6 +15699,13 @@ function OhhwellsBridge() {
|
|
|
16467
15699
|
const [isItemDragging, setIsItemDragging] = (0, import_react17.useState)(false);
|
|
16468
15700
|
const [isFooterFrameSelection, setIsFooterFrameSelection] = (0, import_react17.useState)(false);
|
|
16469
15701
|
isFooterFrameSelectionRef.current = isFooterFrameSelection;
|
|
15702
|
+
const [floatingPanel, setFloatingPanel] = (0, import_react17.useState)(null);
|
|
15703
|
+
const floatingPanelOpenRef = (0, import_react17.useRef)(false);
|
|
15704
|
+
floatingPanelOpenRef.current = floatingPanel !== null;
|
|
15705
|
+
const [floatingPanelPos, setFloatingPanelPos] = (0, import_react17.useState)(null);
|
|
15706
|
+
const [logoSizeDraft, setLogoSizeDraft] = (0, import_react17.useState)(null);
|
|
15707
|
+
const [editorViewport, setEditorViewport] = (0, import_react17.useState)("desktop");
|
|
15708
|
+
const [parentScrollSnap, setParentScrollSnap] = (0, import_react17.useState)(null);
|
|
16470
15709
|
const [navDropdownPreviewOpen, setNavDropdownPreviewOpen] = (0, import_react17.useState)(null);
|
|
16471
15710
|
const [footerHeadingVisible, setFooterHeadingVisible] = (0, import_react17.useState)(null);
|
|
16472
15711
|
const footerDragRef = (0, import_react17.useRef)(null);
|
|
@@ -16481,16 +15720,7 @@ function OhhwellsBridge() {
|
|
|
16481
15720
|
const addNavAfterAnchorRef = (0, import_react17.useRef)(null);
|
|
16482
15721
|
const editContentRef = (0, import_react17.useRef)({});
|
|
16483
15722
|
const aiSectionsRef = (0, import_react17.useRef)("");
|
|
16484
|
-
const brandKitRef = (0, import_react17.useRef)("");
|
|
16485
|
-
const stylesRef = (0, import_react17.useRef)("");
|
|
16486
15723
|
const pendingDeleteUndoRef = (0, import_react17.useRef)(null);
|
|
16487
|
-
const [floatingPanel, setFloatingPanel] = (0, import_react17.useState)(null);
|
|
16488
|
-
const floatingPanelOpenRef = (0, import_react17.useRef)(false);
|
|
16489
|
-
const setFloatingPanelRef = (0, import_react17.useRef)(setFloatingPanel);
|
|
16490
|
-
const [floatingPanelPos, setFloatingPanelPos] = (0, import_react17.useState)(null);
|
|
16491
|
-
const [logoSizeDraft, setLogoSizeDraft] = (0, import_react17.useState)(null);
|
|
16492
|
-
const [editorViewport, setEditorViewport] = (0, import_react17.useState)("desktop");
|
|
16493
|
-
const [parentScrollSnap, setParentScrollSnap] = (0, import_react17.useState)(null);
|
|
16494
15724
|
const [sitePages, setSitePages] = (0, import_react17.useState)([]);
|
|
16495
15725
|
const [sectionsByPath, setSectionsByPath] = (0, import_react17.useState)({});
|
|
16496
15726
|
const sectionsPrefetchGenRef = (0, import_react17.useRef)(0);
|
|
@@ -16499,18 +15729,7 @@ function OhhwellsBridge() {
|
|
|
16499
15729
|
const linkPopoverOpenRef = (0, import_react17.useRef)(false);
|
|
16500
15730
|
const linkPopoverGraceUntilRef = (0, import_react17.useRef)(0);
|
|
16501
15731
|
setLinkPopoverRef.current = setLinkPopover;
|
|
16502
|
-
setFloatingPanelRef.current = setFloatingPanel;
|
|
16503
15732
|
linkPopoverSessionRef.current = linkPopover;
|
|
16504
|
-
floatingPanelOpenRef.current = Boolean(floatingPanel);
|
|
16505
|
-
(0, import_react17.useEffect)(() => {
|
|
16506
|
-
const syncViewport = () => {
|
|
16507
|
-
const next = window.innerWidth <= 480 ? "mobile" : "desktop";
|
|
16508
|
-
setEditorViewport((prev) => prev === next ? prev : next);
|
|
16509
|
-
};
|
|
16510
|
-
syncViewport();
|
|
16511
|
-
window.addEventListener("resize", syncViewport);
|
|
16512
|
-
return () => window.removeEventListener("resize", syncViewport);
|
|
16513
|
-
}, []);
|
|
16514
15733
|
const {
|
|
16515
15734
|
navDragRef,
|
|
16516
15735
|
navDropSlots,
|
|
@@ -17821,31 +17040,15 @@ function OhhwellsBridge() {
|
|
|
17821
17040
|
}
|
|
17822
17041
|
const applyContent = (content) => {
|
|
17823
17042
|
const imageLoads = [];
|
|
17824
|
-
if (typeof content[BRAND_KIT_KEY] === "string") {
|
|
17825
|
-
brandKitRef.current = content[BRAND_KIT_KEY];
|
|
17826
|
-
applyBrandToDom(parseBrandKit(content[BRAND_KIT_KEY]));
|
|
17827
|
-
} else {
|
|
17828
|
-
brandKitRef.current = "";
|
|
17829
|
-
applyBrandToDom(null);
|
|
17830
|
-
}
|
|
17831
17043
|
if (typeof content[AI_SECTIONS_KEY] === "string") {
|
|
17832
17044
|
aiSectionsRef.current = content[AI_SECTIONS_KEY];
|
|
17833
|
-
setAiSectionOrder(content[SECTION_ORDER_KEY], window.location.pathname);
|
|
17834
17045
|
applyAiSectionsToDom(parseAiSectionsState(content[AI_SECTIONS_KEY]));
|
|
17835
17046
|
}
|
|
17836
|
-
if (typeof content[STYLE_STORE_KEY] === "string") {
|
|
17837
|
-
stylesRef.current = content[STYLE_STORE_KEY];
|
|
17838
|
-
applyStylesToDom(parseStyleStore(content[STYLE_STORE_KEY]));
|
|
17839
|
-
}
|
|
17840
|
-
applyBrandChrome(content);
|
|
17841
17047
|
for (const [key, val] of Object.entries(content)) {
|
|
17842
17048
|
if (key === "__ohw_sections") continue;
|
|
17843
17049
|
if (key === AI_SECTIONS_KEY) continue;
|
|
17844
17050
|
if (key === LOGO_PLACEHOLDER_KEY) continue;
|
|
17845
17051
|
if (LOGO_IMAGE_KEYS.includes(key)) continue;
|
|
17846
|
-
if (key === BRAND_KIT_KEY) continue;
|
|
17847
|
-
if (key === STYLE_STORE_KEY) continue;
|
|
17848
|
-
if (BRAND_CHROME_KEYS.has(key)) continue;
|
|
17849
17052
|
if (applyVideoSettingNode(key, val)) continue;
|
|
17850
17053
|
if (applyCarouselNode(key, val)) continue;
|
|
17851
17054
|
document.querySelectorAll(`[data-ohw-key="${key}"]`).forEach((el) => {
|
|
@@ -17911,9 +17114,7 @@ function OhhwellsBridge() {
|
|
|
17911
17114
|
let cancelled = false;
|
|
17912
17115
|
setFetchState("loading");
|
|
17913
17116
|
const apiUrl = process.env.NEXT_PUBLIC_FLOWOPS_API_URL ?? "https://flowops-backend-staging-2yfdh7pwpq-as.a.run.app";
|
|
17914
|
-
|
|
17915
|
-
fetchedContentPaths.add(`${subdomain}::${initialPath}`);
|
|
17916
|
-
fetch(`${apiUrl}/api/public/sites/${subdomain}/content?path=${encodeURIComponent(initialPath)}`, { cache: "no-store" }).then((r2) => r2.ok ? r2.json() : null).then((data) => {
|
|
17117
|
+
fetch(`${apiUrl}/api/public/sites/${subdomain}/content`, { cache: "no-store" }).then((r2) => r2.ok ? r2.json() : null).then((data) => {
|
|
17917
17118
|
if (cancelled) return;
|
|
17918
17119
|
const content = data?.content ?? {};
|
|
17919
17120
|
contentCache.set(subdomain, content);
|
|
@@ -18033,28 +17234,10 @@ function OhhwellsBridge() {
|
|
|
18033
17234
|
initSectionInstancesFromContent(content, window.location.pathname);
|
|
18034
17235
|
observer?.disconnect();
|
|
18035
17236
|
try {
|
|
18036
|
-
applyBrandChrome(content);
|
|
18037
|
-
if (typeof content[BRAND_KIT_KEY] === "string") {
|
|
18038
|
-
applyBrandToDom(parseBrandKit(content[BRAND_KIT_KEY]));
|
|
18039
|
-
} else {
|
|
18040
|
-
applyBrandToDom(null);
|
|
18041
|
-
}
|
|
18042
|
-
if (typeof content[AI_SECTIONS_KEY] === "string") {
|
|
18043
|
-
setAiSectionOrder(content[SECTION_ORDER_KEY], window.location.pathname);
|
|
18044
|
-
applyAiSectionsToDom(parseAiSectionsState(content[AI_SECTIONS_KEY]));
|
|
18045
|
-
}
|
|
18046
|
-
if (typeof content[STYLE_STORE_KEY] === "string") {
|
|
18047
|
-
applyStylesToDom(parseStyleStore(content[STYLE_STORE_KEY]));
|
|
18048
|
-
}
|
|
18049
17237
|
for (const [key, val] of Object.entries(content)) {
|
|
18050
17238
|
if (key === "__ohw_sections") continue;
|
|
18051
|
-
if (key === AI_SECTIONS_KEY) continue;
|
|
18052
17239
|
if (key === LOGO_PLACEHOLDER_KEY) continue;
|
|
18053
17240
|
if (LOGO_IMAGE_KEYS.includes(key)) continue;
|
|
18054
|
-
if (key === BRAND_KIT_KEY) continue;
|
|
18055
|
-
if (key === STYLE_STORE_KEY) continue;
|
|
18056
|
-
if (key === STYLE_STORE_KEY) continue;
|
|
18057
|
-
if (BRAND_CHROME_KEYS.has(key)) continue;
|
|
18058
17241
|
if (applyVideoSettingNode(key, val)) continue;
|
|
18059
17242
|
if (applyCarouselNode(key, val)) continue;
|
|
18060
17243
|
document.querySelectorAll(`[data-ohw-key="${key}"]`).forEach((el) => {
|
|
@@ -18100,17 +17283,6 @@ function OhhwellsBridge() {
|
|
|
18100
17283
|
debounceTimer = setTimeout(applyFromCache, 150);
|
|
18101
17284
|
};
|
|
18102
17285
|
applyFromCache();
|
|
18103
|
-
const pathCacheKey = `${subdomain}::${pathname}`;
|
|
18104
|
-
if (!fetchedContentPaths.has(pathCacheKey)) {
|
|
18105
|
-
fetchedContentPaths.add(pathCacheKey);
|
|
18106
|
-
const apiUrl = process.env.NEXT_PUBLIC_FLOWOPS_API_URL ?? "https://flowops-backend-staging-2yfdh7pwpq-as.a.run.app";
|
|
18107
|
-
fetch(`${apiUrl}/api/public/sites/${subdomain}/content?path=${encodeURIComponent(pathname)}`, { cache: "no-store" }).then((r2) => r2.ok ? r2.json() : null).then((data) => {
|
|
18108
|
-
if (!data?.content) return;
|
|
18109
|
-
contentCache.set(subdomain, data.content);
|
|
18110
|
-
applyFromCache();
|
|
18111
|
-
}).catch(() => {
|
|
18112
|
-
});
|
|
18113
|
-
}
|
|
18114
17286
|
observer = new MutationObserver(scheduleApply);
|
|
18115
17287
|
observer.observe(document.body, { childList: true, subtree: true });
|
|
18116
17288
|
return () => {
|
|
@@ -18206,31 +17378,30 @@ function OhhwellsBridge() {
|
|
|
18206
17378
|
}, [isEditMode, pathname, subdomain, fetchState, resyncSelectedNavigationItem]);
|
|
18207
17379
|
(0, import_react17.useEffect)(() => {
|
|
18208
17380
|
if (!isEditMode) return;
|
|
18209
|
-
let lastPosted = 0;
|
|
18210
17381
|
const measure = () => {
|
|
18211
17382
|
const h = document.body.scrollHeight;
|
|
18212
|
-
if (h > 50
|
|
18213
|
-
lastPosted = h;
|
|
18214
|
-
postToParent2({ type: "ow:height", height: h });
|
|
18215
|
-
}
|
|
18216
|
-
};
|
|
18217
|
-
let raf = null;
|
|
18218
|
-
const schedule = () => {
|
|
18219
|
-
if (raf != null) return;
|
|
18220
|
-
raf = requestAnimationFrame(() => {
|
|
18221
|
-
raf = null;
|
|
18222
|
-
measure();
|
|
18223
|
-
});
|
|
17383
|
+
if (h > 50) postToParent2({ type: "ow:height", height: h });
|
|
18224
17384
|
};
|
|
18225
17385
|
const t1 = setTimeout(measure, 50);
|
|
18226
17386
|
const t2 = setTimeout(measure, 500);
|
|
18227
|
-
|
|
18228
|
-
|
|
17387
|
+
let lastWidth = window.innerWidth;
|
|
17388
|
+
let resizeTimers = [];
|
|
17389
|
+
const clearResizeTimers = () => {
|
|
17390
|
+
resizeTimers.forEach(clearTimeout);
|
|
17391
|
+
resizeTimers = [];
|
|
17392
|
+
};
|
|
17393
|
+
const handleResize = () => {
|
|
17394
|
+
if (window.innerWidth === lastWidth) return;
|
|
17395
|
+
lastWidth = window.innerWidth;
|
|
17396
|
+
clearResizeTimers();
|
|
17397
|
+
resizeTimers = HEIGHT_SETTLE_DELAYS.map((delay) => setTimeout(measure, delay));
|
|
17398
|
+
};
|
|
17399
|
+
window.addEventListener("resize", handleResize);
|
|
18229
17400
|
return () => {
|
|
18230
17401
|
clearTimeout(t1);
|
|
18231
17402
|
clearTimeout(t2);
|
|
18232
|
-
|
|
18233
|
-
|
|
17403
|
+
clearResizeTimers();
|
|
17404
|
+
window.removeEventListener("resize", handleResize);
|
|
18234
17405
|
};
|
|
18235
17406
|
}, [pathname, isEditMode, postToParent2]);
|
|
18236
17407
|
(0, import_react17.useEffect)(() => {
|
|
@@ -18471,7 +17642,6 @@ function OhhwellsBridge() {
|
|
|
18471
17642
|
return;
|
|
18472
17643
|
}
|
|
18473
17644
|
const target = e.target;
|
|
18474
|
-
if (target.closest("[data-ohw-ai-review]")) return;
|
|
18475
17645
|
if (target.closest("[data-ohw-toolbar]")) return;
|
|
18476
17646
|
if (target.closest("[data-ohw-state-toggle]")) return;
|
|
18477
17647
|
if (target.closest("[data-ohw-max-badge]")) return;
|
|
@@ -18483,9 +17653,6 @@ function OhhwellsBridge() {
|
|
|
18483
17653
|
)) {
|
|
18484
17654
|
return;
|
|
18485
17655
|
}
|
|
18486
|
-
if (selectedMediaElRef.current && !selectedMediaElRef.current.contains(target) && !target.closest("[data-ohw-media-overlay], [data-ohw-edit-chrome], [data-ohw-item-interaction]")) {
|
|
18487
|
-
clearMediaSelectionRef.current();
|
|
18488
|
-
}
|
|
18489
17656
|
{
|
|
18490
17657
|
const formEl = getFormElement(target);
|
|
18491
17658
|
const onSuccessText = target.closest(`[${SUCCESS_TEXT_ATTR}]`);
|
|
@@ -18637,14 +17804,19 @@ function OhhwellsBridge() {
|
|
|
18637
17804
|
}
|
|
18638
17805
|
const clickedButton = findClosestButtonLike(target);
|
|
18639
17806
|
const buttonOnMedia = Boolean(clickedButton && isMediaEditable(editable) && editable.contains(clickedButton));
|
|
17807
|
+
console.log("[click-debug]", {
|
|
17808
|
+
editableType: editable.dataset.ohwEditable,
|
|
17809
|
+
editableTag: editable.tagName,
|
|
17810
|
+
targetTag: target.tagName,
|
|
17811
|
+
clickedButtonTag: clickedButton?.tagName ?? null,
|
|
17812
|
+
buttonOnMedia,
|
|
17813
|
+
isMediaEditableEditable: isMediaEditable(editable)
|
|
17814
|
+
});
|
|
18640
17815
|
if (isMediaEditable(editable) && !buttonOnMedia) {
|
|
18641
17816
|
e.preventDefault();
|
|
18642
17817
|
e.stopPropagation();
|
|
18643
|
-
|
|
18644
|
-
|
|
18645
|
-
} else {
|
|
18646
|
-
selectMediaElementRef.current(editable);
|
|
18647
|
-
}
|
|
17818
|
+
aiSectionApiRef.current?.selectFromElement(editable);
|
|
17819
|
+
postToParentRef.current({ type: "ow:image-pick", key: editable.dataset.ohwKey ?? "", elementType: editable.dataset.ohwEditable ?? "image" });
|
|
18648
17820
|
return;
|
|
18649
17821
|
}
|
|
18650
17822
|
const socialItem = getSocialItem(editable);
|
|
@@ -18663,6 +17835,11 @@ function OhhwellsBridge() {
|
|
|
18663
17835
|
const hrefLookupTarget = buttonOnMedia ? clickedButton : editable;
|
|
18664
17836
|
const hrefCtx = getHrefKeyFromElement(hrefLookupTarget);
|
|
18665
17837
|
const navAnchor = hrefCtx ? getNavigationItemAnchor(hrefCtx.anchor) : null;
|
|
17838
|
+
console.log("[click-debug 2]", {
|
|
17839
|
+
hrefLookupTargetTag: hrefLookupTarget.tagName,
|
|
17840
|
+
hrefCtx: hrefCtx ? { key: hrefCtx.key } : null,
|
|
17841
|
+
navAnchorTag: navAnchor?.tagName ?? null
|
|
17842
|
+
});
|
|
18666
17843
|
if (navAnchor) {
|
|
18667
17844
|
e.preventDefault();
|
|
18668
17845
|
e.stopPropagation();
|
|
@@ -18780,7 +17957,6 @@ function OhhwellsBridge() {
|
|
|
18780
17957
|
};
|
|
18781
17958
|
const handleDblClick = (e) => {
|
|
18782
17959
|
const target = e.target;
|
|
18783
|
-
if (target.closest("[data-ohw-ai-review]")) return;
|
|
18784
17960
|
if (target.closest("[data-ohw-toolbar]")) return;
|
|
18785
17961
|
if (target.closest("[data-ohw-state-toggle]")) return;
|
|
18786
17962
|
if (target.closest("[data-ohw-max-badge]")) return;
|
|
@@ -18832,9 +18008,6 @@ function OhhwellsBridge() {
|
|
|
18832
18008
|
setHoveredItemRect(null);
|
|
18833
18009
|
hoveredNavContainerRef.current = null;
|
|
18834
18010
|
setHoveredNavContainerRect(null);
|
|
18835
|
-
siblingHintElRef.current = null;
|
|
18836
|
-
setSiblingHintRect(null);
|
|
18837
|
-
setSiblingHintRects([]);
|
|
18838
18011
|
return;
|
|
18839
18012
|
}
|
|
18840
18013
|
{
|
|
@@ -18953,6 +18126,7 @@ function OhhwellsBridge() {
|
|
|
18953
18126
|
hoveredNavContainerRef.current = null;
|
|
18954
18127
|
setHoveredNavContainerRect(null);
|
|
18955
18128
|
hoveredItemElRef.current = editable;
|
|
18129
|
+
setHoveredItemRect(isSelectedForHoverRef.current(editable) ? null : editable.getBoundingClientRect());
|
|
18956
18130
|
}
|
|
18957
18131
|
}
|
|
18958
18132
|
}
|
|
@@ -19249,7 +18423,7 @@ function OhhwellsBridge() {
|
|
|
19249
18423
|
}
|
|
19250
18424
|
};
|
|
19251
18425
|
const probeImageAt = (clientX, clientY, isDragOver = false, fromParentViewport = false) => {
|
|
19252
|
-
if (linkPopoverOpenRef.current
|
|
18426
|
+
if (linkPopoverOpenRef.current) {
|
|
19253
18427
|
if (hoveredImageRef.current) {
|
|
19254
18428
|
hoveredImageRef.current = null;
|
|
19255
18429
|
hoveredImageHasTextOverlapRef.current = false;
|
|
@@ -19583,9 +18757,7 @@ function OhhwellsBridge() {
|
|
|
19583
18757
|
return;
|
|
19584
18758
|
}
|
|
19585
18759
|
const { y } = toProbeCoords(clientX, clientY, fromParentViewport);
|
|
19586
|
-
const sections = Array.from(document.querySelectorAll("[data-ohw-section]")).
|
|
19587
|
-
(el) => !el.hasAttribute("data-ohw-ai-template-hidden") && !el.hasAttribute("data-ohw-ai-removed") && !el.hasAttribute("data-ohw-ai-replaced-by") && el.getBoundingClientRect().height > 0
|
|
19588
|
-
).sort((a, b) => a.getBoundingClientRect().top - b.getBoundingClientRect().top);
|
|
18760
|
+
const sections = Array.from(document.querySelectorAll("[data-ohw-section]")).sort((a, b) => a.getBoundingClientRect().top - b.getBoundingClientRect().top);
|
|
19589
18761
|
const ZONE = 20;
|
|
19590
18762
|
for (let i = 0; i < sections.length; i++) {
|
|
19591
18763
|
const a = sections[i];
|
|
@@ -19614,7 +18786,8 @@ function OhhwellsBridge() {
|
|
|
19614
18786
|
};
|
|
19615
18787
|
const handleMouseMove = (e) => {
|
|
19616
18788
|
const { clientX, clientY } = e;
|
|
19617
|
-
if (
|
|
18789
|
+
if (pointOwnedByFloatingPanel(clientX, clientY)) return;
|
|
18790
|
+
if (isOverEditorChrome(clientX, clientY)) {
|
|
19618
18791
|
document.querySelectorAll("[data-ohw-hovered]").forEach((el) => el.removeAttribute("data-ohw-hovered"));
|
|
19619
18792
|
formHoverElRef.current = null;
|
|
19620
18793
|
setFormHoverRect(null);
|
|
@@ -19622,12 +18795,6 @@ function OhhwellsBridge() {
|
|
|
19622
18795
|
setHoveredItemRect(null);
|
|
19623
18796
|
hoveredNavContainerRef.current = null;
|
|
19624
18797
|
setHoveredNavContainerRect(null);
|
|
19625
|
-
siblingHintElRef.current = null;
|
|
19626
|
-
setSiblingHintRect(null);
|
|
19627
|
-
setSiblingHintRects([]);
|
|
19628
|
-
dismissImageHover();
|
|
19629
|
-
clearImageHover();
|
|
19630
|
-
setSectionGap(null);
|
|
19631
18798
|
return;
|
|
19632
18799
|
}
|
|
19633
18800
|
if (probeSocialsRowAt(clientX, clientY)) return;
|
|
@@ -19639,11 +18806,7 @@ function OhhwellsBridge() {
|
|
|
19639
18806
|
if (e.data?.type !== "ow:pointer-sync") return;
|
|
19640
18807
|
const { clientX, clientY } = e.data;
|
|
19641
18808
|
if (typeof clientX !== "number" || typeof clientY !== "number") return;
|
|
19642
|
-
if (
|
|
19643
|
-
dismissImageHover();
|
|
19644
|
-
clearImageHover();
|
|
19645
|
-
return;
|
|
19646
|
-
}
|
|
18809
|
+
if (pointOwnedByFloatingPanel(clientX, clientY)) return;
|
|
19647
18810
|
if (probeSocialsRowAt(clientX, clientY)) return;
|
|
19648
18811
|
probeSectionGapAt(clientX, clientY);
|
|
19649
18812
|
probeImageAt(clientX, clientY);
|
|
@@ -19926,23 +19089,10 @@ function OhhwellsBridge() {
|
|
|
19926
19089
|
if (e.data?.type !== "ow:hydrate") return;
|
|
19927
19090
|
const content = e.data.content;
|
|
19928
19091
|
if (!content) return;
|
|
19929
|
-
if (typeof content[BRAND_KIT_KEY] === "string") {
|
|
19930
|
-
brandKitRef.current = content[BRAND_KIT_KEY];
|
|
19931
|
-
applyBrandToDom(parseBrandKit(content[BRAND_KIT_KEY]));
|
|
19932
|
-
} else {
|
|
19933
|
-
brandKitRef.current = "";
|
|
19934
|
-
applyBrandToDom(null);
|
|
19935
|
-
}
|
|
19936
19092
|
if (typeof content[AI_SECTIONS_KEY] === "string") {
|
|
19937
19093
|
aiSectionsRef.current = content[AI_SECTIONS_KEY];
|
|
19938
|
-
setAiSectionOrder(content[SECTION_ORDER_KEY], window.location.pathname);
|
|
19939
19094
|
applyAiSectionsToDom(parseAiSectionsState(content[AI_SECTIONS_KEY]));
|
|
19940
19095
|
}
|
|
19941
|
-
if (typeof content[STYLE_STORE_KEY] === "string") {
|
|
19942
|
-
stylesRef.current = content[STYLE_STORE_KEY];
|
|
19943
|
-
applyStylesToDom(parseStyleStore(content[STYLE_STORE_KEY]));
|
|
19944
|
-
}
|
|
19945
|
-
applyBrandChrome(content);
|
|
19946
19096
|
let sectionsJson = null;
|
|
19947
19097
|
for (const [key, val] of Object.entries(content)) {
|
|
19948
19098
|
if (key === "__ohw_sections") {
|
|
@@ -19952,9 +19102,6 @@ function OhhwellsBridge() {
|
|
|
19952
19102
|
if (key === AI_SECTIONS_KEY) continue;
|
|
19953
19103
|
if (key === LOGO_PLACEHOLDER_KEY) continue;
|
|
19954
19104
|
if (LOGO_IMAGE_KEYS.includes(key) && !String(val ?? "").trim()) continue;
|
|
19955
|
-
if (key === BRAND_KIT_KEY) continue;
|
|
19956
|
-
if (key === STYLE_STORE_KEY) continue;
|
|
19957
|
-
if (BRAND_CHROME_KEYS.has(key)) continue;
|
|
19958
19105
|
if (applyVideoSettingNode(key, val)) continue;
|
|
19959
19106
|
if (applyCarouselNode(key, val)) continue;
|
|
19960
19107
|
document.querySelectorAll(`[data-ohw-key="${key}"]`).forEach((el) => {
|
|
@@ -19968,8 +19115,6 @@ function OhhwellsBridge() {
|
|
|
19968
19115
|
if (video && video.src !== val) applyVideoSrc(video, val);
|
|
19969
19116
|
} else if (el.dataset.ohwEditable === "link") {
|
|
19970
19117
|
applyLinkHref(el, val);
|
|
19971
|
-
} else if (el.dataset.ohwEditable === "icon") {
|
|
19972
|
-
applyIconMarkup(el, val);
|
|
19973
19118
|
} else if (isIconMarkupValue(val)) {
|
|
19974
19119
|
} else {
|
|
19975
19120
|
el.innerHTML = val;
|
|
@@ -20054,21 +19199,12 @@ function OhhwellsBridge() {
|
|
|
20054
19199
|
nodes: collectEditableNodes(editContentRef.current)
|
|
20055
19200
|
});
|
|
20056
19201
|
};
|
|
20057
|
-
const clearInteractionChrome = () => {
|
|
20058
|
-
deactivateRef.current();
|
|
20059
|
-
deselectRef.current();
|
|
20060
|
-
clearMediaSelectionRef.current();
|
|
20061
|
-
};
|
|
20062
19202
|
const handleAiApplyTree = (e) => {
|
|
20063
19203
|
if (e.data?.type !== "ow:ai-apply-tree") return;
|
|
20064
19204
|
const payload = e.data.payload;
|
|
20065
19205
|
if (!payload || typeof payload.id !== "string" || !isRenderableTree(payload.tree)) return;
|
|
20066
|
-
clearInteractionChrome();
|
|
20067
19206
|
const previous = aiSectionsRef.current;
|
|
20068
|
-
const nextState = applyTreeToState(parseAiSectionsState(previous),
|
|
20069
|
-
...payload,
|
|
20070
|
-
path: payload.path ?? window.location.pathname
|
|
20071
|
-
});
|
|
19207
|
+
const nextState = applyTreeToState(parseAiSectionsState(previous), payload);
|
|
20072
19208
|
const nextValue = serializeAiSectionsState(nextState);
|
|
20073
19209
|
aiSectionsRef.current = nextValue;
|
|
20074
19210
|
applyAiSectionsToDom(nextState);
|
|
@@ -20089,7 +19225,6 @@ function OhhwellsBridge() {
|
|
|
20089
19225
|
const exists = document.querySelector(`[data-ohw-section="${CSS.escape(sectionId)}"]`);
|
|
20090
19226
|
if (!exists) return;
|
|
20091
19227
|
if (isPageFrameSection(exists)) return;
|
|
20092
|
-
clearInteractionChrome();
|
|
20093
19228
|
const previous = aiSectionsRef.current;
|
|
20094
19229
|
const nextState = deleteSectionFromState(parseAiSectionsState(previous), sectionId);
|
|
20095
19230
|
const nextValue = serializeAiSectionsState(nextState);
|
|
@@ -20105,10 +19240,8 @@ function OhhwellsBridge() {
|
|
|
20105
19240
|
const handleAiSetSections = (e) => {
|
|
20106
19241
|
if (e.data?.type !== "ow:ai-set-sections") return;
|
|
20107
19242
|
const value = typeof e.data.value === "string" ? e.data.value : "";
|
|
20108
|
-
clearInteractionChrome();
|
|
20109
19243
|
aiSectionsRef.current = value;
|
|
20110
19244
|
applyAiSectionsToDom(parseAiSectionsState(value));
|
|
20111
|
-
applyStylesToDom(parseStyleStore(stylesRef.current));
|
|
20112
19245
|
const restoredHeight = document.body.scrollHeight;
|
|
20113
19246
|
if (restoredHeight > 50) postToParentRef.current({ type: "ow:height", height: restoredHeight });
|
|
20114
19247
|
postToParentRef.current({ type: "ow:change", nodes: [{ key: AI_SECTIONS_KEY, text: value }] });
|
|
@@ -20124,40 +19257,10 @@ function OhhwellsBridge() {
|
|
|
20124
19257
|
if (!entries) return;
|
|
20125
19258
|
const orderJson = JSON.stringify(entries);
|
|
20126
19259
|
editContentRef.current = { ...editContentRef.current, [SECTION_ORDER_KEY]: orderJson };
|
|
20127
|
-
setAiSectionOrder(orderJson, window.location.pathname);
|
|
20128
19260
|
postToParentRef.current({ type: "ow:change", nodes: [{ key: SECTION_ORDER_KEY, text: orderJson }] });
|
|
20129
19261
|
window.dispatchEvent(new Event("resize"));
|
|
20130
19262
|
};
|
|
20131
19263
|
window.addEventListener("message", handleMoveSection);
|
|
20132
|
-
const handleAiSetBrand = (e) => {
|
|
20133
|
-
if (e.data?.type !== "ow:ai-set-brand") return;
|
|
20134
|
-
const value = typeof e.data.value === "string" ? e.data.value : "";
|
|
20135
|
-
const previous = brandKitRef.current;
|
|
20136
|
-
brandKitRef.current = value;
|
|
20137
|
-
applyBrandToDom(parseBrandKit(value));
|
|
20138
|
-
if (aiSectionsRef.current) applyAiSectionsToDom(parseAiSectionsState(aiSectionsRef.current));
|
|
20139
|
-
applyStylesToDom(parseStyleStore(stylesRef.current));
|
|
20140
|
-
postToParentRef.current({ type: "ow:change", nodes: [{ key: BRAND_KIT_KEY, text: value }] });
|
|
20141
|
-
postToParentRef.current({ type: "ow:ai-brand-applied", previous, value });
|
|
20142
|
-
};
|
|
20143
|
-
window.addEventListener("message", handleAiSetBrand);
|
|
20144
|
-
const handleAiSetStyles = (e) => {
|
|
20145
|
-
if (e.data?.type !== "ow:ai-set-styles") return;
|
|
20146
|
-
const value = typeof e.data.value === "string" ? e.data.value : "";
|
|
20147
|
-
const previous = stylesRef.current;
|
|
20148
|
-
stylesRef.current = value;
|
|
20149
|
-
applyStylesToDom(parseStyleStore(value));
|
|
20150
|
-
postToParentRef.current({ type: "ow:change", nodes: [{ key: STYLE_STORE_KEY, text: value }] });
|
|
20151
|
-
postToParentRef.current({ type: "ow:ai-styles-applied", previous, value });
|
|
20152
|
-
};
|
|
20153
|
-
window.addEventListener("message", handleAiSetStyles);
|
|
20154
|
-
const handleGetBrand = (e) => {
|
|
20155
|
-
if (e.data?.type !== "ow:get-brand") return;
|
|
20156
|
-
const template = deriveTemplateBrand();
|
|
20157
|
-
const value = brandKitRef.current || (template ? JSON.stringify(template) : "");
|
|
20158
|
-
postToParentRef.current({ type: "ow:brand-value", value });
|
|
20159
|
-
};
|
|
20160
|
-
window.addEventListener("message", handleGetBrand);
|
|
20161
19264
|
const handlePanelDragging = (e) => {
|
|
20162
19265
|
if (e.data?.type !== "ow:panel-dragging") return;
|
|
20163
19266
|
if (e.data.dragging) document.documentElement.setAttribute("data-ohw-panel-dragging", "");
|
|
@@ -20215,15 +19318,8 @@ function OhhwellsBridge() {
|
|
|
20215
19318
|
closeLinkPopoverRef.current();
|
|
20216
19319
|
return;
|
|
20217
19320
|
}
|
|
20218
|
-
if (floatingPanelOpenRef.current) {
|
|
20219
|
-
setFloatingPanelRef.current(null);
|
|
20220
|
-
deselectRef.current();
|
|
20221
|
-
deactivateRef.current();
|
|
20222
|
-
return;
|
|
20223
|
-
}
|
|
20224
19321
|
deselectRef.current();
|
|
20225
19322
|
deactivateRef.current();
|
|
20226
|
-
clearMediaSelectionRef.current();
|
|
20227
19323
|
};
|
|
20228
19324
|
window.addEventListener("message", handleDeactivate);
|
|
20229
19325
|
const handleToastAction = (e) => {
|
|
@@ -20309,10 +19405,6 @@ function OhhwellsBridge() {
|
|
|
20309
19405
|
const handleKeyDown = (e) => {
|
|
20310
19406
|
if (e.key === "Escape" && document.querySelector("[data-ohw-section-picker]")) return;
|
|
20311
19407
|
if (e.key === "Escape" && document.querySelector("[data-ohw-more-menu]")) return;
|
|
20312
|
-
if (e.key === "Escape" && selectedMediaElRef.current) {
|
|
20313
|
-
clearMediaSelectionRef.current();
|
|
20314
|
-
return;
|
|
20315
|
-
}
|
|
20316
19408
|
if ((e.ctrlKey || e.metaKey) && e.key.toLowerCase() === "a" && activeElRef.current) {
|
|
20317
19409
|
e.preventDefault();
|
|
20318
19410
|
selectAllTextInEditable(activeElRef.current);
|
|
@@ -20472,12 +19564,6 @@ function OhhwellsBridge() {
|
|
|
20472
19564
|
if (aiSectionsRef.current) {
|
|
20473
19565
|
nodes.push({ key: AI_SECTIONS_KEY, type: "sections", text: aiSectionsRef.current });
|
|
20474
19566
|
}
|
|
20475
|
-
if (stylesRef.current) {
|
|
20476
|
-
nodes.push({ key: STYLE_STORE_KEY, type: "styles", text: stylesRef.current });
|
|
20477
|
-
}
|
|
20478
|
-
if (brandKitRef.current) {
|
|
20479
|
-
nodes.push({ key: BRAND_KIT_KEY, type: "brand", text: brandKitRef.current });
|
|
20480
|
-
}
|
|
20481
19567
|
document.querySelectorAll('[data-ohw-editable="form"]').forEach((form) => {
|
|
20482
19568
|
const formKey = formKeyOf(form);
|
|
20483
19569
|
if (!formKey) return;
|
|
@@ -20495,12 +19581,8 @@ function OhhwellsBridge() {
|
|
|
20495
19581
|
if (inserted) {
|
|
20496
19582
|
const tracker = getSectionsTracker();
|
|
20497
19583
|
postToParentRef.current({ type: "ow:change", nodes: [{ key: "__ohw_sections", text: tracker.textContent ?? "[]" }] });
|
|
20498
|
-
const
|
|
20499
|
-
|
|
20500
|
-
if (h > 50) postToParentRef.current({ type: "ow:height", height: h });
|
|
20501
|
-
};
|
|
20502
|
-
reportHeight();
|
|
20503
|
-
setTimeout(reportHeight, 500);
|
|
19584
|
+
const h = document.body.scrollHeight;
|
|
19585
|
+
if (h > 50) postToParentRef.current({ type: "ow:height", height: h });
|
|
20504
19586
|
}
|
|
20505
19587
|
};
|
|
20506
19588
|
const handleSwitchSchedule = (e) => {
|
|
@@ -20897,16 +19979,13 @@ function OhhwellsBridge() {
|
|
|
20897
19979
|
window.removeEventListener("message", handleAiDeleteSection);
|
|
20898
19980
|
window.removeEventListener("message", handleAiSetSections);
|
|
20899
19981
|
window.removeEventListener("message", handleMoveSection);
|
|
20900
|
-
window.removeEventListener("message", handleAiSetBrand);
|
|
20901
|
-
window.removeEventListener("message", handleAiSetStyles);
|
|
20902
|
-
window.removeEventListener("message", handleGetBrand);
|
|
20903
19982
|
window.removeEventListener("message", handlePanelDragging);
|
|
20904
19983
|
window.removeEventListener("message", handleDeleteSection);
|
|
20905
19984
|
window.removeEventListener("message", handleDeactivate);
|
|
19985
|
+
document.documentElement.removeAttribute("data-ohw-panel-dragging");
|
|
20906
19986
|
window.removeEventListener("message", handleToastAction);
|
|
20907
19987
|
window.removeEventListener("message", handleFormCount);
|
|
20908
19988
|
window.removeEventListener("message", handleUiEscape);
|
|
20909
|
-
document.documentElement.removeAttribute("data-ohw-panel-dragging");
|
|
20910
19989
|
autoSaveTimers.current.forEach(clearTimeout);
|
|
20911
19990
|
autoSaveTimers.current.clear();
|
|
20912
19991
|
if (imageUnhoverTimerRef.current) clearTimeout(imageUnhoverTimerRef.current);
|
|
@@ -21516,22 +20595,11 @@ function OhhwellsBridge() {
|
|
|
21516
20595
|
const showEditLink = toolbarShowEditLink;
|
|
21517
20596
|
const currentSections = sectionsByPath[pathname] ?? [];
|
|
21518
20597
|
linkPopoverOpenRef.current = linkPopover !== null;
|
|
21519
|
-
const handleMediaSelect = (0, import_react17.useCallback)((key) => {
|
|
21520
|
-
const el = hoveredImageRef.current?.dataset.ohwKey === key ? hoveredImageRef.current : Array.from(document.querySelectorAll(MEDIA_SELECTOR)).find(
|
|
21521
|
-
(m) => (m.dataset.ohwKey ?? "") === key
|
|
21522
|
-
) ?? null;
|
|
21523
|
-
if (!el) return;
|
|
21524
|
-
selectMediaElementRef.current(el);
|
|
21525
|
-
}, []);
|
|
21526
20598
|
const handleMediaReplace = (0, import_react17.useCallback)(
|
|
21527
20599
|
(key) => {
|
|
21528
|
-
postToParent2({
|
|
21529
|
-
type: "ow:image-pick",
|
|
21530
|
-
key,
|
|
21531
|
-
elementType: mediaHover?.elementType ?? selectedMedia?.elementType ?? "image"
|
|
21532
|
-
});
|
|
20600
|
+
postToParent2({ type: "ow:image-pick", key, elementType: mediaHover?.elementType ?? "image" });
|
|
21533
20601
|
},
|
|
21534
|
-
[postToParent2, mediaHover?.elementType
|
|
20602
|
+
[postToParent2, mediaHover?.elementType]
|
|
21535
20603
|
);
|
|
21536
20604
|
const handleEditCarousel = (0, import_react17.useCallback)(
|
|
21537
20605
|
(key) => {
|
|
@@ -21603,25 +20671,12 @@ function OhhwellsBridge() {
|
|
|
21603
20671
|
},
|
|
21604
20672
|
`uploading-${key}`
|
|
21605
20673
|
)),
|
|
21606
|
-
mediaHover && !(mediaHover.key in uploadingRects) &&
|
|
20674
|
+
mediaHover && !(mediaHover.key in uploadingRects) && /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
|
|
21607
20675
|
MediaOverlay,
|
|
21608
20676
|
{
|
|
21609
20677
|
hover: mediaHover,
|
|
21610
20678
|
isUploading: false,
|
|
21611
20679
|
onReplace: handleMediaReplace,
|
|
21612
|
-
onSelect: handleMediaSelect,
|
|
21613
|
-
onVideoSettingsChange: handleVideoSettingsChange
|
|
21614
|
-
}
|
|
21615
|
-
),
|
|
21616
|
-
selectedMedia && !(selectedMedia.key in uploadingRects) && !linkPopover && /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
|
|
21617
|
-
MediaOverlay,
|
|
21618
|
-
{
|
|
21619
|
-
hover: selectedMedia,
|
|
21620
|
-
selected: true,
|
|
21621
|
-
hovered: mediaHover?.key === selectedMedia.key,
|
|
21622
|
-
isUploading: false,
|
|
21623
|
-
onReplace: handleMediaReplace,
|
|
21624
|
-
onSelect: handleMediaSelect,
|
|
21625
20680
|
onVideoSettingsChange: handleVideoSettingsChange
|
|
21626
20681
|
}
|
|
21627
20682
|
),
|
|
@@ -22027,59 +21082,6 @@ function OhhwellsBridge() {
|
|
|
22027
21082
|
) : null
|
|
22028
21083
|
] });
|
|
22029
21084
|
}
|
|
22030
|
-
|
|
22031
|
-
// src/ui/EmptySection.tsx
|
|
22032
|
-
var import_link = __toESM(require("next/link"), 1);
|
|
22033
|
-
var import_jsx_runtime34 = require("react/jsx-runtime");
|
|
22034
|
-
function EmptySection({ title, homeHref = "/", eyebrowKey, titleKey, subtitleKey }) {
|
|
22035
|
-
return /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)(import_jsx_runtime34.Fragment, { children: [
|
|
22036
|
-
/* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
|
|
22037
|
-
"p",
|
|
22038
|
-
{
|
|
22039
|
-
style: {
|
|
22040
|
-
fontFamily: "var(--brand-font-body)",
|
|
22041
|
-
fontSize: "0.75rem",
|
|
22042
|
-
fontWeight: 500,
|
|
22043
|
-
letterSpacing: "0.15em",
|
|
22044
|
-
textTransform: "uppercase",
|
|
22045
|
-
color: "var(--brand-accent)",
|
|
22046
|
-
marginBottom: "1.5rem"
|
|
22047
|
-
},
|
|
22048
|
-
children: /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(import_link.default, { href: homeHref, style: { color: "inherit" }, children: /* @__PURE__ */ (0, import_jsx_runtime34.jsx)("span", { ...eyebrowKey ? { "data-ohw-editable": "text", "data-ohw-key": eyebrowKey } : {}, children: "Home" }) })
|
|
22049
|
-
}
|
|
22050
|
-
),
|
|
22051
|
-
/* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
|
|
22052
|
-
"h1",
|
|
22053
|
-
{
|
|
22054
|
-
style: {
|
|
22055
|
-
fontFamily: "var(--brand-font-heading)",
|
|
22056
|
-
fontSize: "clamp(2rem, 3.5vw, 2.75rem)",
|
|
22057
|
-
lineHeight: 1.1,
|
|
22058
|
-
letterSpacing: "-0.025em",
|
|
22059
|
-
color: "var(--brand-text)",
|
|
22060
|
-
marginBottom: "1rem"
|
|
22061
|
-
},
|
|
22062
|
-
...titleKey ? { "data-ohw-editable": "text", "data-ohw-key": titleKey, "data-ohw-max-length": 80 } : {},
|
|
22063
|
-
children: title
|
|
22064
|
-
}
|
|
22065
|
-
),
|
|
22066
|
-
/* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
|
|
22067
|
-
"p",
|
|
22068
|
-
{
|
|
22069
|
-
style: {
|
|
22070
|
-
fontFamily: "var(--brand-font-body)",
|
|
22071
|
-
fontSize: "1rem",
|
|
22072
|
-
lineHeight: 1.7,
|
|
22073
|
-
fontWeight: 300,
|
|
22074
|
-
color: "var(--brand-text-muted)",
|
|
22075
|
-
maxWidth: "340px"
|
|
22076
|
-
},
|
|
22077
|
-
...subtitleKey ? { "data-ohw-editable": "text", "data-ohw-key": subtitleKey, "data-ohw-max-length": 160 } : {},
|
|
22078
|
-
children: "This page doesn't have any content yet."
|
|
22079
|
-
}
|
|
22080
|
-
)
|
|
22081
|
-
] });
|
|
22082
|
-
}
|
|
22083
21085
|
// Annotate the CommonJS export names for ESM import in node:
|
|
22084
21086
|
0 && (module.exports = {
|
|
22085
21087
|
AI_DEFAULT_BRAND,
|
|
@@ -22097,7 +21099,6 @@ function EmptySection({ title, homeHref = "/", eyebrowKey, titleKey, subtitleKey
|
|
|
22097
21099
|
DropdownMenuItem,
|
|
22098
21100
|
DropdownMenuSeparator,
|
|
22099
21101
|
DropdownMenuTrigger,
|
|
22100
|
-
EmptySection,
|
|
22101
21102
|
ItemActionToolbar,
|
|
22102
21103
|
ItemInteractionLayer,
|
|
22103
21104
|
LinkEditorPanel,
|