@ohhwells/bridge 0.1.59 → 0.1.60-next.171
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 +1649 -188
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +17 -3
- package/dist/index.d.ts +17 -3
- package/dist/index.js +1646 -186
- package/dist/index.js.map +1 -1
- package/dist/pages.cjs +141 -0
- package/dist/pages.cjs.map +1 -0
- package/dist/pages.js +107 -0
- package/dist/pages.js.map +1 -0
- package/dist/styles.css +61 -0
- package/package.json +6 -1
package/dist/index.cjs
CHANGED
|
@@ -46,6 +46,7 @@ __export(index_exports, {
|
|
|
46
46
|
DropdownMenuItem: () => DropdownMenuItem,
|
|
47
47
|
DropdownMenuSeparator: () => DropdownMenuSeparator,
|
|
48
48
|
DropdownMenuTrigger: () => DropdownMenuTrigger,
|
|
49
|
+
EmptySection: () => EmptySection,
|
|
49
50
|
ItemActionToolbar: () => ItemActionToolbar,
|
|
50
51
|
ItemInteractionLayer: () => ItemInteractionLayer,
|
|
51
52
|
LinkEditorPanel: () => LinkEditorPanel,
|
|
@@ -169,6 +170,7 @@ function applyTreeToState(state, payload) {
|
|
|
169
170
|
const entry = {
|
|
170
171
|
id: payload.id,
|
|
171
172
|
label: payload.label ?? "Generated section",
|
|
173
|
+
...typeof payload.path === "string" && payload.path ? { path: payload.path } : {},
|
|
172
174
|
afterSection: payload.mode === "insert" && !insertBefore ? payload.targetSectionId ?? null : null,
|
|
173
175
|
...insertBefore && payload.targetSectionId ? { beforeSection: payload.targetSectionId } : {},
|
|
174
176
|
...payload.mode === "replace" && payload.targetSectionId ? { replaces: payload.targetSectionId } : {},
|
|
@@ -191,6 +193,272 @@ function deleteSectionFromState(state, sectionId) {
|
|
|
191
193
|
return { ...state, v: 1, sections: state.sections, removed: [...removed, sectionId] };
|
|
192
194
|
}
|
|
193
195
|
|
|
196
|
+
// src/lib/brand-chrome.ts
|
|
197
|
+
var BRAND_NAME_KEY = "__ohw_brand_name";
|
|
198
|
+
var BRAND_TITLE_KEY = "__ohw_site_title";
|
|
199
|
+
var BRAND_FAVICON_LETTER_KEY = "__ohw_favicon_letter";
|
|
200
|
+
var BRAND_CHROME_KEYS = /* @__PURE__ */ new Set([
|
|
201
|
+
BRAND_NAME_KEY,
|
|
202
|
+
BRAND_TITLE_KEY,
|
|
203
|
+
BRAND_FAVICON_LETTER_KEY
|
|
204
|
+
]);
|
|
205
|
+
function upsertMeta(selector, attr, token, value) {
|
|
206
|
+
let el = document.head.querySelector(selector);
|
|
207
|
+
if (!el) {
|
|
208
|
+
el = document.createElement("meta");
|
|
209
|
+
el.setAttribute(attr, token);
|
|
210
|
+
document.head.appendChild(el);
|
|
211
|
+
}
|
|
212
|
+
if (el.getAttribute("content") !== value) el.setAttribute("content", value);
|
|
213
|
+
}
|
|
214
|
+
function escapeXml(value) {
|
|
215
|
+
return value.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """).replace(/'/g, "'");
|
|
216
|
+
}
|
|
217
|
+
function applyLetterFavicon(letter) {
|
|
218
|
+
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>`;
|
|
219
|
+
const href = `data:image/svg+xml,${encodeURIComponent(svg)}`;
|
|
220
|
+
let link = document.head.querySelector('link[rel="icon"]');
|
|
221
|
+
if (!link) {
|
|
222
|
+
link = document.createElement("link");
|
|
223
|
+
link.rel = "icon";
|
|
224
|
+
document.head.appendChild(link);
|
|
225
|
+
}
|
|
226
|
+
link.type = "image/svg+xml";
|
|
227
|
+
if (link.href !== href) link.href = href;
|
|
228
|
+
}
|
|
229
|
+
function applyBrandChrome(content) {
|
|
230
|
+
const name = content[BRAND_NAME_KEY];
|
|
231
|
+
if (typeof name === "string" && name.length > 0) {
|
|
232
|
+
document.querySelectorAll("[data-ohw-wordmark]").forEach((el) => {
|
|
233
|
+
if (el.textContent !== name) el.textContent = name;
|
|
234
|
+
if (el.getAttribute("title") !== name) el.setAttribute("title", name);
|
|
235
|
+
});
|
|
236
|
+
}
|
|
237
|
+
const title = content[BRAND_TITLE_KEY];
|
|
238
|
+
if (typeof title === "string" && title.length > 0) {
|
|
239
|
+
if (document.title !== title) document.title = title;
|
|
240
|
+
upsertMeta('meta[property="og:title"]', "property", "og:title", title);
|
|
241
|
+
upsertMeta('meta[name="twitter:title"]', "name", "twitter:title", title);
|
|
242
|
+
}
|
|
243
|
+
const letter = content[BRAND_FAVICON_LETTER_KEY];
|
|
244
|
+
if (typeof letter === "string" && letter.length > 0) {
|
|
245
|
+
applyLetterFavicon(letter);
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
// src/lib/brand-kit.ts
|
|
250
|
+
var BRAND_KIT_KEY = "__ohw_brand";
|
|
251
|
+
var BRAND_VAR_PREFIX = "--ohw-brand-";
|
|
252
|
+
var BRAND_VAR_NAMES = ["primary", "accent", "light", "dark", "surface", "border", "muted"].map(
|
|
253
|
+
(role) => `${BRAND_VAR_PREFIX}${role}`
|
|
254
|
+
);
|
|
255
|
+
var FONT_VARS = { heading: ["--font-heading", "--font-display"], body: ["--font-body"] };
|
|
256
|
+
var BRAND_FONT_LINK_ID = "ohw-brand-fonts";
|
|
257
|
+
function brandColorVars(kit) {
|
|
258
|
+
const { dark, primary, accent, light } = kit.palette;
|
|
259
|
+
const mix = (a, aPct, b) => `color-mix(in srgb, ${a} ${aPct}%, ${b})`;
|
|
260
|
+
return {
|
|
261
|
+
[`${BRAND_VAR_PREFIX}primary`]: primary,
|
|
262
|
+
[`${BRAND_VAR_PREFIX}accent`]: accent,
|
|
263
|
+
[`${BRAND_VAR_PREFIX}light`]: light,
|
|
264
|
+
[`${BRAND_VAR_PREFIX}dark`]: dark,
|
|
265
|
+
[`${BRAND_VAR_PREFIX}surface`]: mix(light, 95, dark),
|
|
266
|
+
[`${BRAND_VAR_PREFIX}border`]: mix(light, 85, dark),
|
|
267
|
+
[`${BRAND_VAR_PREFIX}muted`]: mix(dark, 62, light)
|
|
268
|
+
};
|
|
269
|
+
}
|
|
270
|
+
function parseBrandKit(raw) {
|
|
271
|
+
if (!raw) return null;
|
|
272
|
+
try {
|
|
273
|
+
const parsed = JSON.parse(raw);
|
|
274
|
+
const p = parsed?.palette;
|
|
275
|
+
const f = parsed?.fonts;
|
|
276
|
+
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") {
|
|
277
|
+
return null;
|
|
278
|
+
}
|
|
279
|
+
return {
|
|
280
|
+
palette: { dark: p.dark, primary: p.primary, accent: p.accent, light: p.light },
|
|
281
|
+
fonts: { heading: f.heading, body: f.body }
|
|
282
|
+
};
|
|
283
|
+
} catch {
|
|
284
|
+
return null;
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
function familyOf(stack) {
|
|
288
|
+
const first = stack.split(",")[0]?.trim() ?? "";
|
|
289
|
+
return first.replace(/^['"]|['"]$/g, "");
|
|
290
|
+
}
|
|
291
|
+
function loadBrandFonts(families) {
|
|
292
|
+
const unique = [...new Set(families.map((f) => f.trim()).filter(Boolean))];
|
|
293
|
+
if (unique.length === 0) return;
|
|
294
|
+
const spec = unique.map((f) => `${f.replace(/ /g, "+")}:400,500,600,700`).join("|");
|
|
295
|
+
const href = `https://fonts.googleapis.com/css?family=${spec}&display=swap`;
|
|
296
|
+
let link = document.getElementById(BRAND_FONT_LINK_ID);
|
|
297
|
+
if (!link) {
|
|
298
|
+
link = document.createElement("link");
|
|
299
|
+
link.id = BRAND_FONT_LINK_ID;
|
|
300
|
+
link.rel = "stylesheet";
|
|
301
|
+
document.head.appendChild(link);
|
|
302
|
+
}
|
|
303
|
+
if (link.href !== href) link.href = href;
|
|
304
|
+
}
|
|
305
|
+
function applyBrandToDom(kit) {
|
|
306
|
+
const root = document.documentElement;
|
|
307
|
+
if (!kit) {
|
|
308
|
+
for (const name of BRAND_VAR_NAMES) root.style.removeProperty(name);
|
|
309
|
+
for (const name of [...FONT_VARS.heading, ...FONT_VARS.body]) root.style.removeProperty(name);
|
|
310
|
+
document.getElementById(BRAND_FONT_LINK_ID)?.remove();
|
|
311
|
+
return;
|
|
312
|
+
}
|
|
313
|
+
for (const [name, value] of Object.entries(brandColorVars(kit))) root.style.setProperty(name, value);
|
|
314
|
+
for (const name of FONT_VARS.heading) root.style.setProperty(name, kit.fonts.heading);
|
|
315
|
+
for (const name of FONT_VARS.body) root.style.setProperty(name, kit.fonts.body);
|
|
316
|
+
loadBrandFonts([familyOf(kit.fonts.heading), familyOf(kit.fonts.body)]);
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
// src/lib/section-styles.ts
|
|
320
|
+
var STYLE_STORE_KEY = "__ohw_styles";
|
|
321
|
+
var STYLE_SHEET_ID = "ohw-section-styles";
|
|
322
|
+
function parseStyleStore(raw) {
|
|
323
|
+
if (!raw) return null;
|
|
324
|
+
try {
|
|
325
|
+
const parsed = JSON.parse(raw);
|
|
326
|
+
if (parsed?.v !== 1) return null;
|
|
327
|
+
return {
|
|
328
|
+
v: 1,
|
|
329
|
+
sections: typeof parsed.sections === "object" && parsed.sections ? parsed.sections : {},
|
|
330
|
+
nodes: typeof parsed.nodes === "object" && parsed.nodes ? parsed.nodes : {}
|
|
331
|
+
};
|
|
332
|
+
} catch {
|
|
333
|
+
return null;
|
|
334
|
+
}
|
|
335
|
+
}
|
|
336
|
+
var BG_VALUES = {
|
|
337
|
+
surface: "color-mix(in srgb, var(--ohw-brand-light, var(--color-light, #ECECEB)) 94%, var(--ohw-brand-dark, var(--color-dark, #0C0A09)))",
|
|
338
|
+
accent: "var(--ohw-brand-primary, var(--color-primary, #0078E5))",
|
|
339
|
+
"accent-soft": "color-mix(in srgb, var(--ohw-brand-primary, var(--color-primary, #0078E5)) 12%, var(--ohw-brand-light, var(--color-light, #FFFFFF)))"
|
|
340
|
+
};
|
|
341
|
+
var HEADLINE_SIZES = { md: 24, lg: 32, xl: 40, display: 56 };
|
|
342
|
+
function styleSheetCss() {
|
|
343
|
+
const rules = [];
|
|
344
|
+
for (const [tone, value] of Object.entries(BG_VALUES)) {
|
|
345
|
+
rules.push(`[data-ohw-style-bg="${tone}"] { background: ${value} !important; }`);
|
|
346
|
+
}
|
|
347
|
+
rules.push(
|
|
348
|
+
`[data-ohw-style-bg="accent"] { color: var(--ohw-brand-light, var(--color-light, #FFFFFF)) !important; }`
|
|
349
|
+
);
|
|
350
|
+
rules.push(
|
|
351
|
+
`[data-ohw-style-distribution="space-between"] { display: flex !important; flex-direction: column; justify-content: space-between; }`,
|
|
352
|
+
`[data-ohw-style-distribution="center"] { display: flex !important; flex-direction: column; justify-content: center; }`
|
|
353
|
+
);
|
|
354
|
+
for (const [scale, size] of Object.entries(HEADLINE_SIZES)) {
|
|
355
|
+
rules.push(
|
|
356
|
+
`[data-ohw-style-headline="${scale}"] :is(h1, h2, h3) { font-size: ${size}px !important; line-height: 1.15 !important; }`
|
|
357
|
+
);
|
|
358
|
+
}
|
|
359
|
+
rules.push(
|
|
360
|
+
`[data-ohw-style-aspect="fill-height"] img { height: 100% !important; aspect-ratio: auto !important; object-fit: cover; }`
|
|
361
|
+
);
|
|
362
|
+
for (const aspect of ["1:1", "4:5", "3:4", "3:2", "16:9", "2:1", "3:1"]) {
|
|
363
|
+
rules.push(
|
|
364
|
+
`[data-ohw-style-aspect="${aspect.replace(":", "-")}"] img { aspect-ratio: ${aspect.replace(":", " / ")} !important; height: auto !important; object-fit: cover; }`
|
|
365
|
+
);
|
|
366
|
+
}
|
|
367
|
+
const pad = { tight: 40, balanced: 64, airy: 96 };
|
|
368
|
+
for (const [spacing, px] of Object.entries(pad)) {
|
|
369
|
+
rules.push(
|
|
370
|
+
`[data-ohw-style-spacing="${spacing}"] { padding-top: ${px}px !important; padding-bottom: ${px}px !important; }`
|
|
371
|
+
);
|
|
372
|
+
}
|
|
373
|
+
return rules.join("\n");
|
|
374
|
+
}
|
|
375
|
+
var SECTION_ATTRS = {
|
|
376
|
+
sectionBackground: "data-ohw-style-bg",
|
|
377
|
+
textDistribution: "data-ohw-style-distribution",
|
|
378
|
+
headlineScale: "data-ohw-style-headline",
|
|
379
|
+
imageAspect: "data-ohw-style-aspect",
|
|
380
|
+
spacing: "data-ohw-style-spacing"
|
|
381
|
+
};
|
|
382
|
+
var NODE_WROTE_ATTR = "data-ohw-style-node";
|
|
383
|
+
function ensureStyleSheet() {
|
|
384
|
+
let el = document.getElementById(STYLE_SHEET_ID);
|
|
385
|
+
if (!el) {
|
|
386
|
+
el = document.createElement("style");
|
|
387
|
+
el.id = STYLE_SHEET_ID;
|
|
388
|
+
document.head.appendChild(el);
|
|
389
|
+
}
|
|
390
|
+
const css = styleSheetCss();
|
|
391
|
+
if (el.textContent !== css) el.textContent = css;
|
|
392
|
+
}
|
|
393
|
+
function clearSectionAttrs(root) {
|
|
394
|
+
for (const attr of Object.values(SECTION_ATTRS)) {
|
|
395
|
+
for (const el of Array.from(root.querySelectorAll(`[${attr}]`))) el.removeAttribute(attr);
|
|
396
|
+
}
|
|
397
|
+
for (const el of Array.from(root.querySelectorAll("[data-ohw-style-bgcolor]"))) {
|
|
398
|
+
;
|
|
399
|
+
el.style.removeProperty("background");
|
|
400
|
+
el.removeAttribute("data-ohw-style-bgcolor");
|
|
401
|
+
}
|
|
402
|
+
}
|
|
403
|
+
function clearNodeProps(root) {
|
|
404
|
+
for (const el of Array.from(root.querySelectorAll(`[${NODE_WROTE_ATTR}]`))) {
|
|
405
|
+
const h = el;
|
|
406
|
+
h.style.removeProperty("color");
|
|
407
|
+
h.style.removeProperty("font-size");
|
|
408
|
+
h.style.removeProperty("background");
|
|
409
|
+
h.removeAttribute(NODE_WROTE_ATTR);
|
|
410
|
+
}
|
|
411
|
+
}
|
|
412
|
+
function buttonSurfaceOf(el) {
|
|
413
|
+
return el.closest("a, button") ?? el;
|
|
414
|
+
}
|
|
415
|
+
function applyStylesToDom(store) {
|
|
416
|
+
ensureStyleSheet();
|
|
417
|
+
clearSectionAttrs(document);
|
|
418
|
+
clearNodeProps(document);
|
|
419
|
+
if (!store) return;
|
|
420
|
+
for (const [sectionId, override] of Object.entries(store.sections)) {
|
|
421
|
+
const sections = document.querySelectorAll(
|
|
422
|
+
`[data-ohw-section="${CSS.escape(sectionId)}"]`
|
|
423
|
+
);
|
|
424
|
+
for (const section of Array.from(sections)) {
|
|
425
|
+
for (const [prop, attr] of Object.entries(SECTION_ATTRS)) {
|
|
426
|
+
const value = override[prop];
|
|
427
|
+
if (value === void 0) continue;
|
|
428
|
+
if (prop === "sectionBackground" && override.sectionBackgroundColor !== void 0) continue;
|
|
429
|
+
section.setAttribute(attr, String(value).replace(":", "-"));
|
|
430
|
+
}
|
|
431
|
+
if (override.sectionBackgroundColor !== void 0) {
|
|
432
|
+
section.style.setProperty("background", override.sectionBackgroundColor, "important");
|
|
433
|
+
section.setAttribute("data-ohw-style-bgcolor", "");
|
|
434
|
+
}
|
|
435
|
+
}
|
|
436
|
+
}
|
|
437
|
+
for (const [key, override] of Object.entries(store.nodes)) {
|
|
438
|
+
const nodes = document.querySelectorAll(`[data-ohw-key="${CSS.escape(key)}"]`);
|
|
439
|
+
for (const el of Array.from(nodes)) {
|
|
440
|
+
if (override.color !== void 0) {
|
|
441
|
+
el.style.setProperty("color", override.color, "important");
|
|
442
|
+
el.setAttribute(NODE_WROTE_ATTR, "");
|
|
443
|
+
}
|
|
444
|
+
if (override.fontSize !== void 0) {
|
|
445
|
+
el.style.setProperty("font-size", `${override.fontSize}px`, "important");
|
|
446
|
+
el.setAttribute(NODE_WROTE_ATTR, "");
|
|
447
|
+
}
|
|
448
|
+
if (override.buttonBackground !== void 0 || override.buttonText !== void 0) {
|
|
449
|
+
const surface = buttonSurfaceOf(el);
|
|
450
|
+
if (override.buttonBackground !== void 0) {
|
|
451
|
+
surface.style.setProperty("background", override.buttonBackground, "important");
|
|
452
|
+
}
|
|
453
|
+
if (override.buttonText !== void 0) {
|
|
454
|
+
surface.style.setProperty("color", override.buttonText, "important");
|
|
455
|
+
}
|
|
456
|
+
surface.setAttribute(NODE_WROTE_ATTR, "");
|
|
457
|
+
}
|
|
458
|
+
}
|
|
459
|
+
}
|
|
460
|
+
}
|
|
461
|
+
|
|
194
462
|
// src/ui/ai-tree/aiSectionsManager.tsx
|
|
195
463
|
var import_react_dom = require("react-dom");
|
|
196
464
|
var import_client = require("react-dom/client");
|
|
@@ -205,7 +473,8 @@ function lucideByName(name) {
|
|
|
205
473
|
}
|
|
206
474
|
var typeStyle = (spec, font) => ({
|
|
207
475
|
fontFamily: font,
|
|
208
|
-
|
|
476
|
+
// Headings shrink with the viewport (reaching full size around ~900px wide); body copy stays put.
|
|
477
|
+
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,
|
|
209
478
|
lineHeight: spec.line,
|
|
210
479
|
fontWeight: spec.weight
|
|
211
480
|
});
|
|
@@ -223,6 +492,19 @@ var FEATURE_LINE_CSS = [
|
|
|
223
492
|
function textAttrs(ctx, path) {
|
|
224
493
|
return ctx.keyFor ? { "data-ohw-key": ctx.keyFor(path), "data-ohw-editable": "text" } : {};
|
|
225
494
|
}
|
|
495
|
+
var AI_RESPONSIVE_CSS = [
|
|
496
|
+
"@media (max-width: 960px) {",
|
|
497
|
+
" [data-ai-responsive] [data-ai-grid] { grid-template-columns: repeat(2, 1fr) !important; }",
|
|
498
|
+
' [data-ai-responsive] [data-ai-grid="1"] { grid-template-columns: 1fr !important; }',
|
|
499
|
+
"}",
|
|
500
|
+
"@media (max-width: 640px) {",
|
|
501
|
+
" [data-ai-responsive] [data-ai-grid] { grid-template-columns: 1fr !important; }",
|
|
502
|
+
" [data-ai-responsive] [data-ai-columns] > * { grid-column: 1 / -1 !important; }",
|
|
503
|
+
" [data-ai-responsive] [data-ai-section-inner] { padding-left: 20px !important; padding-right: 20px !important; }",
|
|
504
|
+
" [data-ai-responsive] { overflow-x: hidden; }",
|
|
505
|
+
" [data-ai-responsive] img { max-width: 100%; }",
|
|
506
|
+
"}"
|
|
507
|
+
].join("\n");
|
|
226
508
|
var TRANSPARENT_PX = "data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7";
|
|
227
509
|
function MediaBox({
|
|
228
510
|
refValue,
|
|
@@ -965,6 +1247,7 @@ function Carousel({ items, itemsPerRow, ctx }) {
|
|
|
965
1247
|
children: pageGroups.map((group, p) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
966
1248
|
"div",
|
|
967
1249
|
{
|
|
1250
|
+
"data-ai-grid": String(itemsPerRow),
|
|
968
1251
|
style: {
|
|
969
1252
|
flex: "0 0 100%",
|
|
970
1253
|
display: "grid",
|
|
@@ -1068,6 +1351,7 @@ function CollectionBlock({ node, ctx, path }) {
|
|
|
1068
1351
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1069
1352
|
"div",
|
|
1070
1353
|
{
|
|
1354
|
+
"data-ai-grid": String(itemsPerRow),
|
|
1071
1355
|
style: {
|
|
1072
1356
|
display: "grid",
|
|
1073
1357
|
gridTemplateColumns: `repeat(${itemsPerRow}, 1fr)`,
|
|
@@ -1226,24 +1510,42 @@ function AiTreeRenderer({ tree, brand, resolveMedia, editKeyPrefix }) {
|
|
|
1226
1510
|
const overlayAlpha = { low: 0.25, medium: 0.45, high: 0.65 }[settings.overlayIntensity ?? "medium"];
|
|
1227
1511
|
const backgroundUrl = isOverlay && settings.backgroundMedia ? ctx.resolveMedia(settings.backgroundMedia) : null;
|
|
1228
1512
|
const bgAttrs = ctx.keyFor && isOverlay && settings.backgroundMedia ? { "data-ohw-key": ctx.keyFor("settings.backgroundMedia"), "data-ohw-editable": "bg-image" } : {};
|
|
1513
|
+
const toneBackground = (() => {
|
|
1514
|
+
const { dark, primary, light } = resolvedBrand.palette;
|
|
1515
|
+
switch (settings.sectionBackground) {
|
|
1516
|
+
case "surface":
|
|
1517
|
+
return `color-mix(in srgb, ${light} 94%, ${dark})`;
|
|
1518
|
+
case "accent":
|
|
1519
|
+
return primary;
|
|
1520
|
+
case "accent-soft":
|
|
1521
|
+
return `color-mix(in srgb, ${primary} 12%, ${light})`;
|
|
1522
|
+
default:
|
|
1523
|
+
return void 0;
|
|
1524
|
+
}
|
|
1525
|
+
})();
|
|
1526
|
+
const distributed = !isOverlay && settings.textDistribution;
|
|
1229
1527
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
1230
1528
|
"section",
|
|
1231
1529
|
{
|
|
1232
1530
|
"data-ai-section": tree.tag ?? "",
|
|
1233
1531
|
...bgAttrs,
|
|
1532
|
+
"data-ai-responsive": "",
|
|
1234
1533
|
style: {
|
|
1235
1534
|
position: "relative",
|
|
1236
1535
|
padding: `${pad}px 0`,
|
|
1237
|
-
background: isOverlay && !backgroundUrl ? "#DBEAFE" : void 0,
|
|
1536
|
+
background: toneBackground ?? (isOverlay && !backgroundUrl ? "#DBEAFE" : void 0),
|
|
1238
1537
|
backgroundImage: backgroundUrl ? `url(${backgroundUrl})` : void 0,
|
|
1239
1538
|
backgroundSize: "cover",
|
|
1240
|
-
backgroundPosition: "center"
|
|
1539
|
+
backgroundPosition: "center",
|
|
1540
|
+
color: settings.sectionBackground === "accent" ? resolvedBrand.palette.light : void 0
|
|
1241
1541
|
},
|
|
1242
1542
|
children: [
|
|
1543
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("style", { children: AI_RESPONSIVE_CSS }),
|
|
1243
1544
|
isOverlay && backgroundUrl && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: { position: "absolute", inset: 0, background: `rgba(255,255,255,${overlayAlpha})` } }),
|
|
1244
1545
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1245
1546
|
"div",
|
|
1246
1547
|
{
|
|
1548
|
+
"data-ai-section-inner": "",
|
|
1247
1549
|
style: {
|
|
1248
1550
|
position: "relative",
|
|
1249
1551
|
maxWidth: AI_TREE_TOKENS.sectionMaxWidth,
|
|
@@ -1254,14 +1556,29 @@ function AiTreeRenderer({ tree, brand, resolveMedia, editKeyPrefix }) {
|
|
|
1254
1556
|
children: tree.rows.map((row, r2) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1255
1557
|
"div",
|
|
1256
1558
|
{
|
|
1559
|
+
"data-ai-columns": "",
|
|
1257
1560
|
style: {
|
|
1258
1561
|
display: "grid",
|
|
1259
1562
|
gridTemplateColumns: "repeat(12, 1fr)",
|
|
1260
1563
|
gap: AI_TREE_TOKENS.spacing6,
|
|
1261
|
-
alignItems: settings.verticalPosition === "top" ? "start" : "center",
|
|
1564
|
+
alignItems: distributed === "space-between" ? "stretch" : (distributed ?? settings.verticalPosition) === "top" ? "start" : "center",
|
|
1262
1565
|
marginTop: r2 > 0 ? AI_TREE_TOKENS.spacing8 : 0
|
|
1263
1566
|
},
|
|
1264
|
-
children: (row.blocks ?? []).map((block, b) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1567
|
+
children: (row.blocks ?? []).map((block, b) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1568
|
+
"div",
|
|
1569
|
+
{
|
|
1570
|
+
"data-ai-cell": "",
|
|
1571
|
+
style: {
|
|
1572
|
+
gridColumn: `span ${Math.min(12, Math.max(1, block.span))}`,
|
|
1573
|
+
minWidth: 0,
|
|
1574
|
+
// space-between: each column becomes a flex column whose content spreads over
|
|
1575
|
+
// the full row height instead of clumping at the top.
|
|
1576
|
+
...distributed === "space-between" ? { display: "flex", flexDirection: "column", justifyContent: "space-between" } : {}
|
|
1577
|
+
},
|
|
1578
|
+
children: renderNode(block, ctx, `r${r2}.b${b}`)
|
|
1579
|
+
},
|
|
1580
|
+
b
|
|
1581
|
+
))
|
|
1265
1582
|
},
|
|
1266
1583
|
r2
|
|
1267
1584
|
))
|
|
@@ -1277,17 +1594,34 @@ var import_jsx_runtime2 = require("react/jsx-runtime");
|
|
|
1277
1594
|
var CONTAINER_ATTR = "data-ohw-ai-generated";
|
|
1278
1595
|
var REPLACED_ATTR = "data-ohw-ai-replaced-by";
|
|
1279
1596
|
var REMOVED_ATTR = "data-ohw-ai-removed";
|
|
1597
|
+
function readRootVar(name) {
|
|
1598
|
+
if (typeof document === "undefined") return "";
|
|
1599
|
+
return getComputedStyle(document.documentElement).getPropertyValue(name).trim();
|
|
1600
|
+
}
|
|
1601
|
+
function deriveBrandOverride() {
|
|
1602
|
+
const dark = readRootVar("--ohw-brand-dark");
|
|
1603
|
+
const primary = readRootVar("--ohw-brand-primary");
|
|
1604
|
+
const light = readRootVar("--ohw-brand-light");
|
|
1605
|
+
if (!dark || !primary || !light) return null;
|
|
1606
|
+
const accent = readRootVar("--ohw-brand-accent");
|
|
1607
|
+
const heading = readRootVar("--font-heading") || readRootVar("--font-display");
|
|
1608
|
+
const body = readRootVar("--font-body");
|
|
1609
|
+
return {
|
|
1610
|
+
palette: { dark, primary, accent: accent || dark, light },
|
|
1611
|
+
fonts: {
|
|
1612
|
+
heading: heading || AI_DEFAULT_BRAND.fonts.heading,
|
|
1613
|
+
body: body || AI_DEFAULT_BRAND.fonts.body
|
|
1614
|
+
}
|
|
1615
|
+
};
|
|
1616
|
+
}
|
|
1280
1617
|
function deriveTemplateBrand() {
|
|
1281
|
-
|
|
1282
|
-
const
|
|
1283
|
-
const
|
|
1284
|
-
const dark = read("--color-dark");
|
|
1285
|
-
const primary = read("--color-primary");
|
|
1286
|
-
const light = read("--color-light");
|
|
1618
|
+
const dark = readRootVar("--color-dark");
|
|
1619
|
+
const primary = readRootVar("--color-primary");
|
|
1620
|
+
const light = readRootVar("--color-light");
|
|
1287
1621
|
if (!dark || !primary || !light) return null;
|
|
1288
|
-
const accent =
|
|
1289
|
-
const heading =
|
|
1290
|
-
const body =
|
|
1622
|
+
const accent = readRootVar("--color-accent");
|
|
1623
|
+
const heading = readRootVar("--font-heading") || readRootVar("--font-display");
|
|
1624
|
+
const body = readRootVar("--font-body");
|
|
1291
1625
|
return {
|
|
1292
1626
|
palette: { dark, primary, accent: accent || dark, light },
|
|
1293
1627
|
fonts: {
|
|
@@ -1379,8 +1713,12 @@ function syncReplacedOriginals(state) {
|
|
|
1379
1713
|
}
|
|
1380
1714
|
function applyAiSectionsToDom(state, options) {
|
|
1381
1715
|
if (typeof document === "undefined") return;
|
|
1716
|
+
const brandOverride = deriveBrandOverride();
|
|
1382
1717
|
const templateBrand = deriveTemplateBrand();
|
|
1383
|
-
const
|
|
1718
|
+
const brandKey = brandOverride ? JSON.stringify(brandOverride) : "";
|
|
1719
|
+
const pagePath = window.location.pathname;
|
|
1720
|
+
const pageSections = state.sections.filter((entry) => !entry.path || entry.path === pagePath);
|
|
1721
|
+
const activeIds = new Set(pageSections.map((entry) => entry.id));
|
|
1384
1722
|
for (const [id, section] of mounted) {
|
|
1385
1723
|
if (!activeIds.has(id)) {
|
|
1386
1724
|
section.root.unmount();
|
|
@@ -1388,8 +1726,8 @@ function applyAiSectionsToDom(state, options) {
|
|
|
1388
1726
|
mounted.delete(id);
|
|
1389
1727
|
}
|
|
1390
1728
|
}
|
|
1391
|
-
for (const entry of
|
|
1392
|
-
const serialized = JSON.stringify(entry);
|
|
1729
|
+
for (const entry of pageSections) {
|
|
1730
|
+
const serialized = JSON.stringify(entry) + brandKey;
|
|
1393
1731
|
const existing = mounted.get(entry.id);
|
|
1394
1732
|
if (existing && existing.serialized === serialized && existing.container.isConnected) {
|
|
1395
1733
|
continue;
|
|
@@ -1403,6 +1741,7 @@ function applyAiSectionsToDom(state, options) {
|
|
|
1403
1741
|
mounted.delete(entry.id);
|
|
1404
1742
|
}
|
|
1405
1743
|
container.setAttribute("data-ohw-section", entry.id);
|
|
1744
|
+
container.setAttribute("data-ohw-instance", entry.id);
|
|
1406
1745
|
container.setAttribute("data-ohw-section-label", entry.label);
|
|
1407
1746
|
placeContainer(container, entry);
|
|
1408
1747
|
const root = mounted.get(entry.id)?.root ?? (0, import_client.createRoot)(container);
|
|
@@ -1413,7 +1752,7 @@ function applyAiSectionsToDom(state, options) {
|
|
|
1413
1752
|
AiTreeRenderer,
|
|
1414
1753
|
{
|
|
1415
1754
|
tree: entry.tree,
|
|
1416
|
-
brand: entry.brand ?? options?.brand ?? templateBrand ?? void 0,
|
|
1755
|
+
brand: brandOverride ?? entry.brand ?? options?.brand ?? templateBrand ?? void 0,
|
|
1417
1756
|
resolveMedia,
|
|
1418
1757
|
editKeyPrefix: `ai.${entry.id}`
|
|
1419
1758
|
}
|
|
@@ -2030,7 +2369,7 @@ function SchedulingWidget({ notifyOnConnect = false, initialScheduleId, insertAf
|
|
|
2030
2369
|
const autoId = (0, import_react5.useId)();
|
|
2031
2370
|
const insertAfter = insertAfterProp ?? autoId;
|
|
2032
2371
|
const [schedule, setSchedule] = (0, import_react5.useState)(null);
|
|
2033
|
-
const [loading, setLoading] = (0, import_react5.useState)(
|
|
2372
|
+
const [loading, setLoading] = (0, import_react5.useState)(initialScheduleId !== null);
|
|
2034
2373
|
const [inEditor, setInEditor] = (0, import_react5.useState)(false);
|
|
2035
2374
|
const [isHovered, setIsHovered] = (0, import_react5.useState)(false);
|
|
2036
2375
|
const [modalState, setModalState] = (0, import_react5.useState)(null);
|
|
@@ -2204,8 +2543,10 @@ function SchedulingWidget({ notifyOnConnect = false, initialScheduleId, insertAf
|
|
|
2204
2543
|
"*"
|
|
2205
2544
|
);
|
|
2206
2545
|
};
|
|
2207
|
-
if (!inEditor && !loading && !schedule) return null;
|
|
2208
2546
|
const sectionId = `scheduling-${insertAfter}`;
|
|
2547
|
+
if (!inEditor && !loading && !schedule) {
|
|
2548
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("section", { "data-ohw-section": sectionId, "data-ohw-scheduling-anchor": insertAfter, style: { display: "none" } });
|
|
2549
|
+
}
|
|
2209
2550
|
return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
|
|
2210
2551
|
"section",
|
|
2211
2552
|
{
|
|
@@ -6159,6 +6500,7 @@ var FOCUS_RING = `0 0 0 4px color-mix(in srgb, ${PRIMARY} 12%, transparent)`;
|
|
|
6159
6500
|
var DRAG_SHADOW = "0px 4px 6px -1px rgba(0, 0, 0, 0.1), 0px 2px 4px -2px rgba(0, 0, 0, 0.1)";
|
|
6160
6501
|
var TOOLBAR_EDGE_MARGIN = 4;
|
|
6161
6502
|
var SELECTION_CHROME_GAP = 4;
|
|
6503
|
+
var HOVER_CHROME_GAP = 2;
|
|
6162
6504
|
var TOOLBAR_STROKE_GAP = 4;
|
|
6163
6505
|
function getChromeZIndex(state) {
|
|
6164
6506
|
switch (state) {
|
|
@@ -6314,10 +6656,11 @@ function ItemInteractionLayer({
|
|
|
6314
6656
|
onItemPointerDown,
|
|
6315
6657
|
onItemClick,
|
|
6316
6658
|
itemDragSurface = true,
|
|
6317
|
-
chromeGap
|
|
6659
|
+
chromeGap,
|
|
6318
6660
|
className
|
|
6319
6661
|
}) {
|
|
6320
6662
|
if (state === "default") return null;
|
|
6663
|
+
const gap = chromeGap ?? (state === "hover" ? HOVER_CHROME_GAP : SELECTION_CHROME_GAP);
|
|
6321
6664
|
const isActive = state === "active-top" || state === "active-bottom";
|
|
6322
6665
|
const isDragging = state === "dragging";
|
|
6323
6666
|
const showToolbar = isActive && toolbar;
|
|
@@ -6333,10 +6676,10 @@ function ItemInteractionLayer({
|
|
|
6333
6676
|
className: cn("pointer-events-none", className),
|
|
6334
6677
|
style: {
|
|
6335
6678
|
position: "fixed",
|
|
6336
|
-
top: rect.top -
|
|
6337
|
-
left: rect.left -
|
|
6338
|
-
width: rect.width +
|
|
6339
|
-
height: rect.height +
|
|
6679
|
+
top: rect.top - gap,
|
|
6680
|
+
left: rect.left - gap,
|
|
6681
|
+
width: rect.width + gap * 2,
|
|
6682
|
+
height: rect.height + gap * 2,
|
|
6340
6683
|
zIndex: getChromeZIndex(state)
|
|
6341
6684
|
},
|
|
6342
6685
|
children: [
|
|
@@ -6722,8 +7065,12 @@ function parseSectionsFromHtml(html) {
|
|
|
6722
7065
|
|
|
6723
7066
|
// src/ui/ai-section/AiSectionOverlay.tsx
|
|
6724
7067
|
var import_jsx_runtime16 = require("react/jsx-runtime");
|
|
6725
|
-
function
|
|
6726
|
-
const
|
|
7068
|
+
function findSectionElement(instanceId) {
|
|
7069
|
+
const escaped = CSS.escape(instanceId);
|
|
7070
|
+
return document.querySelector(`[data-ohw-instance="${escaped}"]`) ?? document.querySelector(`[data-ohw-section="${escaped}"]:not([data-ohw-instance])`);
|
|
7071
|
+
}
|
|
7072
|
+
function readRect(instanceId) {
|
|
7073
|
+
const el = findSectionElement(instanceId);
|
|
6727
7074
|
if (!el) return null;
|
|
6728
7075
|
const r2 = el.getBoundingClientRect();
|
|
6729
7076
|
if (r2.width <= 0 || r2.height <= 0) return null;
|
|
@@ -6746,7 +7093,7 @@ function useLiveSectionRect(sectionId) {
|
|
|
6746
7093
|
const opts = { capture: true, passive: true };
|
|
6747
7094
|
window.addEventListener("scroll", update, opts);
|
|
6748
7095
|
window.addEventListener("resize", update);
|
|
6749
|
-
const el =
|
|
7096
|
+
const el = findSectionElement(sectionId);
|
|
6750
7097
|
const ro = el ? new ResizeObserver(update) : null;
|
|
6751
7098
|
if (el && ro) ro.observe(el);
|
|
6752
7099
|
const interval = setInterval(update, 500);
|
|
@@ -6759,6 +7106,14 @@ function useLiveSectionRect(sectionId) {
|
|
|
6759
7106
|
}, [sectionId]);
|
|
6760
7107
|
return rect;
|
|
6761
7108
|
}
|
|
7109
|
+
function computeSectionBoundaryFlags(instanceId) {
|
|
7110
|
+
const topLevel = Array.from(document.querySelectorAll("[data-ohw-section]")).filter(
|
|
7111
|
+
(el) => !el.parentElement?.closest("[data-ohw-section]")
|
|
7112
|
+
);
|
|
7113
|
+
const index = topLevel.findIndex((el) => (el.dataset.ohwInstance ?? el.dataset.ohwSection) === instanceId);
|
|
7114
|
+
if (index === -1) return { isFirst: true, isLast: true };
|
|
7115
|
+
return { isFirst: index === 0, isLast: index === topLevel.length - 1 };
|
|
7116
|
+
}
|
|
6762
7117
|
var PRIMARY2 = "#0885FE";
|
|
6763
7118
|
function edgeAwareRadius(rect) {
|
|
6764
7119
|
const container = window.innerWidth <= 480 ? 16 : 24;
|
|
@@ -6840,7 +7195,7 @@ function AiSectionOverlay({
|
|
|
6840
7195
|
(el) => {
|
|
6841
7196
|
postToParent2({
|
|
6842
7197
|
type: "ow:section-selected",
|
|
6843
|
-
sectionId: el
|
|
7198
|
+
sectionId: el ? el.dataset.ohwInstance ?? el.dataset.ohwSection ?? null : null,
|
|
6844
7199
|
sectionLabel: el ? el.dataset.ohwSectionLabel ?? titleCaseSectionId(el.dataset.ohwSection ?? "") : null
|
|
6845
7200
|
});
|
|
6846
7201
|
},
|
|
@@ -6849,7 +7204,7 @@ function AiSectionOverlay({
|
|
|
6849
7204
|
const selectFromElement = (0, import_react8.useCallback)(
|
|
6850
7205
|
(el, options) => {
|
|
6851
7206
|
const sectionEl = el?.closest("[data-ohw-section]") ?? null;
|
|
6852
|
-
const id = sectionEl
|
|
7207
|
+
const id = sectionEl ? sectionEl.dataset.ohwInstance ?? sectionEl.dataset.ohwSection ?? null : null;
|
|
6853
7208
|
if (id === selectedIdRef.current) return;
|
|
6854
7209
|
setSelectedId(id);
|
|
6855
7210
|
if (options?.report !== false) report(sectionEl);
|
|
@@ -6892,7 +7247,7 @@ function AiSectionOverlay({
|
|
|
6892
7247
|
setReviewId(found ? sectionId : null);
|
|
6893
7248
|
postToParent2({ type: "ow:ai-review-started", sectionId, found });
|
|
6894
7249
|
if (found) {
|
|
6895
|
-
document.querySelector(`[data-ohw-
|
|
7250
|
+
document.querySelector(`[data-ohw-instance="${CSS.escape(sectionId)}"]`)?.scrollIntoView({ behavior: "smooth", block: "nearest" });
|
|
6896
7251
|
}
|
|
6897
7252
|
}
|
|
6898
7253
|
};
|
|
@@ -6911,7 +7266,7 @@ function AiSectionOverlay({
|
|
|
6911
7266
|
return;
|
|
6912
7267
|
}
|
|
6913
7268
|
const sec = t.closest("[data-ohw-section]");
|
|
6914
|
-
setHoveredId(sec
|
|
7269
|
+
setHoveredId(sec ? sec.dataset.ohwInstance ?? sec.dataset.ohwSection ?? null : null);
|
|
6915
7270
|
};
|
|
6916
7271
|
const onLeave = () => setHoveredId(null);
|
|
6917
7272
|
document.addEventListener("mousemove", onMove, { passive: true });
|
|
@@ -6943,9 +7298,29 @@ function AiSectionOverlay({
|
|
|
6943
7298
|
},
|
|
6944
7299
|
[postToParent2]
|
|
6945
7300
|
);
|
|
6946
|
-
const
|
|
7301
|
+
const activeSelectionId = reviewId ? null : selectedId;
|
|
7302
|
+
const selectionRect = useLiveSectionRect(activeSelectionId);
|
|
6947
7303
|
const reviewRect = useLiveSectionRect(reviewId);
|
|
6948
7304
|
const hoverRect = useLiveSectionRect(reviewId || hoveredId === selectedId ? null : hoveredId);
|
|
7305
|
+
(0, import_react8.useEffect)(() => {
|
|
7306
|
+
if (!activeSelectionId || !selectionRect) {
|
|
7307
|
+
postToParent2({ type: "ow:section-rect", instanceId: null, rect: null });
|
|
7308
|
+
return;
|
|
7309
|
+
}
|
|
7310
|
+
const { isFirst, isLast } = computeSectionBoundaryFlags(activeSelectionId);
|
|
7311
|
+
postToParent2({
|
|
7312
|
+
type: "ow:section-rect",
|
|
7313
|
+
instanceId: activeSelectionId,
|
|
7314
|
+
rect: {
|
|
7315
|
+
top: selectionRect.top + window.scrollY,
|
|
7316
|
+
left: selectionRect.left + window.scrollX,
|
|
7317
|
+
width: selectionRect.width,
|
|
7318
|
+
height: selectionRect.height
|
|
7319
|
+
},
|
|
7320
|
+
isFirst,
|
|
7321
|
+
isLast
|
|
7322
|
+
});
|
|
7323
|
+
}, [activeSelectionId, selectionRect, postToParent2]);
|
|
6949
7324
|
return /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(import_jsx_runtime16.Fragment, { children: [
|
|
6950
7325
|
hoverRect && /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
|
|
6951
7326
|
"div",
|
|
@@ -6996,7 +7371,10 @@ function AiSectionOverlay({
|
|
|
6996
7371
|
border: `2px solid ${PRIMARY2}`,
|
|
6997
7372
|
borderRadius: edgeAwareRadius(reviewRect),
|
|
6998
7373
|
zIndex: 2147483200,
|
|
6999
|
-
// The veil itself: swallows clicks so the section stays locked until decided.
|
|
7374
|
+
// The veil itself: swallows clicks so the section stays locked until decided. This
|
|
7375
|
+
// stopPropagation only guards the bubble phase; the bridge's capture-phase click
|
|
7376
|
+
// handlers additionally bail on `[data-ohw-ai-review]`, without which a click on
|
|
7377
|
+
// Accept/Discard resolves to the media beneath and opens the file picker.
|
|
7000
7378
|
background: "rgba(8, 133, 254, 0.04)",
|
|
7001
7379
|
pointerEvents: "auto",
|
|
7002
7380
|
cursor: "default"
|
|
@@ -9690,6 +10068,10 @@ function isSocialsRow(el) {
|
|
|
9690
10068
|
const anchors = Array.from(el.querySelectorAll("a"));
|
|
9691
10069
|
return anchors.length > 0 && anchors.every((anchor) => isSocialItem(anchor));
|
|
9692
10070
|
}
|
|
10071
|
+
var MAX_SOCIAL_ITEMS_PER_ROW = 7;
|
|
10072
|
+
function canAddSocialItem(row) {
|
|
10073
|
+
return listSocialItems(row).length < MAX_SOCIAL_ITEMS_PER_ROW;
|
|
10074
|
+
}
|
|
9693
10075
|
function listSocialItems(row) {
|
|
9694
10076
|
return Array.from(row.children).map((child) => {
|
|
9695
10077
|
if (!(child instanceof HTMLElement)) return null;
|
|
@@ -10049,6 +10431,7 @@ function ensureIconSlot(item) {
|
|
|
10049
10431
|
// src/lib/footer-items.ts
|
|
10050
10432
|
var FOOTER_ORDER_KEY = "__ohw_footer_order";
|
|
10051
10433
|
var MAX_FOOTER_COLUMNS = 18;
|
|
10434
|
+
var MAX_FOOTER_ITEMS_PER_COLUMN = 7;
|
|
10052
10435
|
var FOOTER_HREF_RE = /^footer-(\d+)-(\d+)-href$/;
|
|
10053
10436
|
function parseFooterHrefKey(key) {
|
|
10054
10437
|
if (!key) return null;
|
|
@@ -10266,6 +10649,13 @@ function getNextFooterColumnIndex() {
|
|
|
10266
10649
|
function canAddFooterColumn() {
|
|
10267
10650
|
return listFooterColumns().length < MAX_FOOTER_COLUMNS;
|
|
10268
10651
|
}
|
|
10652
|
+
function canAddFooterItem(column) {
|
|
10653
|
+
return listFooterLinksInColumn(column).length < MAX_FOOTER_ITEMS_PER_COLUMN;
|
|
10654
|
+
}
|
|
10655
|
+
function resolveFooterColumnForAdd(selected) {
|
|
10656
|
+
if (selected.hasAttribute("data-ohw-footer-col")) return selected;
|
|
10657
|
+
return selected.closest("[data-ohw-footer-col]") ?? (listFooterColumns().includes(selected) ? selected : null);
|
|
10658
|
+
}
|
|
10269
10659
|
function buildFooterHeading(colIndex, text) {
|
|
10270
10660
|
const heading = document.createElement("p");
|
|
10271
10661
|
heading.setAttribute("data-ohw-editable", "text");
|
|
@@ -10890,6 +11280,329 @@ function deleteFooterColumn(column) {
|
|
|
10890
11280
|
};
|
|
10891
11281
|
}
|
|
10892
11282
|
|
|
11283
|
+
// src/lib/logo-identity.ts
|
|
11284
|
+
var LOGO_TEXT_KEYS = ["nav-logo-text", "footer-logo-text", "logo-text"];
|
|
11285
|
+
var LOGO_IMAGE_KEYS = ["nav-logo-image", "footer-logo", "footer-logo-image"];
|
|
11286
|
+
var LOGO_HREF_KEYS = ["nav-logo-href", "footer-logo-href", "logo-href"];
|
|
11287
|
+
var LOGO_PLACEHOLDER_KEY = "logo-is-placeholder";
|
|
11288
|
+
var LOGO_ALT_KEY = "logo-alt";
|
|
11289
|
+
var LOGO_IMAGE_URL_KEY = "nav-logo-image";
|
|
11290
|
+
var PLACEHOLDER_BUSINESS_NAME = "Business name";
|
|
11291
|
+
function resolveLogoDisplayText(text) {
|
|
11292
|
+
const trimmed = (text ?? "").trim();
|
|
11293
|
+
return trimmed || PLACEHOLDER_BUSINESS_NAME;
|
|
11294
|
+
}
|
|
11295
|
+
function isFooterLogoRoot(root) {
|
|
11296
|
+
return Boolean(root.closest("footer") || root.closest('[data-ohw-section="footer"]'));
|
|
11297
|
+
}
|
|
11298
|
+
function imageKeyForRoot(root) {
|
|
11299
|
+
return isFooterLogoRoot(root) ? "footer-logo" : "nav-logo-image";
|
|
11300
|
+
}
|
|
11301
|
+
function textKeyForRoot(root) {
|
|
11302
|
+
return isFooterLogoRoot(root) ? "footer-logo-text" : "nav-logo-text";
|
|
11303
|
+
}
|
|
11304
|
+
function ensureLogoHrefKey(root) {
|
|
11305
|
+
if (!(root instanceof HTMLAnchorElement)) return;
|
|
11306
|
+
if (root.hasAttribute("data-ohw-href-key")) return;
|
|
11307
|
+
root.setAttribute("data-ohw-href-key", isFooterLogoRoot(root) ? "footer-logo-href" : "nav-logo-href");
|
|
11308
|
+
}
|
|
11309
|
+
function applyLogoIdentity(text, isPlaceholder) {
|
|
11310
|
+
const display = resolveLogoDisplayText(text);
|
|
11311
|
+
const placeholder = isPlaceholder || !text.trim() || display === PLACEHOLDER_BUSINESS_NAME;
|
|
11312
|
+
for (const key of LOGO_TEXT_KEYS) {
|
|
11313
|
+
document.querySelectorAll(`[data-ohw-key="${key}"]`).forEach((el) => {
|
|
11314
|
+
if (el.textContent !== display) el.textContent = display;
|
|
11315
|
+
});
|
|
11316
|
+
}
|
|
11317
|
+
for (const key of LOGO_IMAGE_KEYS) {
|
|
11318
|
+
document.querySelectorAll(`[data-ohw-key="${key}"]`).forEach((el) => {
|
|
11319
|
+
const img = el instanceof HTMLImageElement ? el : el.querySelector("img");
|
|
11320
|
+
if (img) img.alt = display;
|
|
11321
|
+
});
|
|
11322
|
+
}
|
|
11323
|
+
document.querySelectorAll('[data-ohw-role="logo"], [data-ohw-logo]').forEach((el) => {
|
|
11324
|
+
if (placeholder) el.setAttribute("data-ohw-placeholder", "");
|
|
11325
|
+
else el.removeAttribute("data-ohw-placeholder");
|
|
11326
|
+
});
|
|
11327
|
+
return display;
|
|
11328
|
+
}
|
|
11329
|
+
function applyLogoImage(url, alt) {
|
|
11330
|
+
const displayAlt = resolveLogoDisplayText(alt);
|
|
11331
|
+
document.querySelectorAll('[data-ohw-role="logo"], [data-ohw-logo]').forEach((root) => {
|
|
11332
|
+
ensureLogoHrefKey(root);
|
|
11333
|
+
const imageKey = imageKeyForRoot(root);
|
|
11334
|
+
const textKey = textKeyForRoot(root);
|
|
11335
|
+
let img = root.querySelector(`img[data-ohw-key="${imageKey}"]`) ?? (root.querySelector(`[data-ohw-key="${imageKey}"]`) instanceof HTMLImageElement ? root.querySelector(`[data-ohw-key="${imageKey}"]`) : null) ?? root.querySelector("img");
|
|
11336
|
+
let textEl = root.querySelector(`[data-ohw-key="${textKey}"]`) ?? root.querySelector('[data-ohw-key="logo-text"]');
|
|
11337
|
+
if (url) {
|
|
11338
|
+
if (!img) {
|
|
11339
|
+
img = document.createElement("img");
|
|
11340
|
+
img.setAttribute("data-ohw-editable", "image");
|
|
11341
|
+
img.setAttribute("data-ohw-key", imageKey);
|
|
11342
|
+
img.alt = displayAlt;
|
|
11343
|
+
img.style.height = "";
|
|
11344
|
+
img.style.maxHeight = "none";
|
|
11345
|
+
img.style.width = "auto";
|
|
11346
|
+
img.style.display = "block";
|
|
11347
|
+
img.style.objectFit = "contain";
|
|
11348
|
+
root.insertBefore(img, root.firstChild);
|
|
11349
|
+
} else {
|
|
11350
|
+
img.setAttribute("data-ohw-editable", "image");
|
|
11351
|
+
img.setAttribute("data-ohw-key", imageKey);
|
|
11352
|
+
}
|
|
11353
|
+
img.removeAttribute("srcset");
|
|
11354
|
+
img.removeAttribute("sizes");
|
|
11355
|
+
img.src = url;
|
|
11356
|
+
img.alt = displayAlt;
|
|
11357
|
+
img.style.display = "block";
|
|
11358
|
+
if (textEl) textEl.style.display = "none";
|
|
11359
|
+
root.removeAttribute("data-ohw-placeholder");
|
|
11360
|
+
return;
|
|
11361
|
+
}
|
|
11362
|
+
if (img) {
|
|
11363
|
+
img.removeAttribute("src");
|
|
11364
|
+
img.removeAttribute("srcset");
|
|
11365
|
+
img.removeAttribute("sizes");
|
|
11366
|
+
img.alt = displayAlt;
|
|
11367
|
+
img.style.display = "none";
|
|
11368
|
+
}
|
|
11369
|
+
if (!textEl) {
|
|
11370
|
+
textEl = document.createElement("span");
|
|
11371
|
+
textEl.setAttribute("data-ohw-editable", "plain");
|
|
11372
|
+
textEl.setAttribute("data-ohw-key", textKey);
|
|
11373
|
+
root.appendChild(textEl);
|
|
11374
|
+
}
|
|
11375
|
+
textEl.style.display = "";
|
|
11376
|
+
if (textEl.textContent !== displayAlt) textEl.textContent = displayAlt;
|
|
11377
|
+
if (!displayAlt.trim() || displayAlt === PLACEHOLDER_BUSINESS_NAME) {
|
|
11378
|
+
root.setAttribute("data-ohw-placeholder", "");
|
|
11379
|
+
} else {
|
|
11380
|
+
root.removeAttribute("data-ohw-placeholder");
|
|
11381
|
+
}
|
|
11382
|
+
});
|
|
11383
|
+
}
|
|
11384
|
+
function applyLogoHref(href) {
|
|
11385
|
+
const target = href.trim() || "/";
|
|
11386
|
+
document.querySelectorAll('[data-ohw-role="logo"], [data-ohw-logo]').forEach((root) => {
|
|
11387
|
+
ensureLogoHrefKey(root);
|
|
11388
|
+
if (root instanceof HTMLAnchorElement) {
|
|
11389
|
+
root.setAttribute("href", target);
|
|
11390
|
+
}
|
|
11391
|
+
});
|
|
11392
|
+
for (const key of LOGO_HREF_KEYS) setStoredLinkHref(key, target);
|
|
11393
|
+
}
|
|
11394
|
+
function readLogoIdentityFromDom() {
|
|
11395
|
+
let imageUrl = null;
|
|
11396
|
+
for (const key of LOGO_IMAGE_KEYS) {
|
|
11397
|
+
const el = document.querySelector(`[data-ohw-key="${key}"]`);
|
|
11398
|
+
const img = el instanceof HTMLImageElement ? el : el?.querySelector("img");
|
|
11399
|
+
const attrSrc = img?.getAttribute("src")?.trim() ?? "";
|
|
11400
|
+
if (attrSrc && !attrSrc.startsWith("data:") && img && img.style.display !== "none") {
|
|
11401
|
+
imageUrl = img.currentSrc || img.src;
|
|
11402
|
+
break;
|
|
11403
|
+
}
|
|
11404
|
+
}
|
|
11405
|
+
let text = PLACEHOLDER_BUSINESS_NAME;
|
|
11406
|
+
let isPlaceholder = true;
|
|
11407
|
+
for (const key of LOGO_TEXT_KEYS) {
|
|
11408
|
+
const el = document.querySelector(`[data-ohw-key="${key}"]`);
|
|
11409
|
+
if (el?.textContent?.trim()) {
|
|
11410
|
+
text = el.textContent.trim();
|
|
11411
|
+
const logoRoot2 = el.closest('[data-ohw-role="logo"], [data-ohw-logo]');
|
|
11412
|
+
isPlaceholder = logoRoot2?.hasAttribute("data-ohw-placeholder") === true || text === PLACEHOLDER_BUSINESS_NAME;
|
|
11413
|
+
break;
|
|
11414
|
+
}
|
|
11415
|
+
}
|
|
11416
|
+
if (imageUrl) {
|
|
11417
|
+
const logoImg = document.querySelector(
|
|
11418
|
+
'[data-ohw-key="nav-logo-image"], [data-ohw-key="footer-logo"]'
|
|
11419
|
+
);
|
|
11420
|
+
const alt = logoImg?.alt?.trim() || text;
|
|
11421
|
+
isPlaceholder = false;
|
|
11422
|
+
const hrefEl = document.querySelector(
|
|
11423
|
+
'a[data-ohw-role="logo"], a[data-ohw-logo], [data-ohw-role="logo"]'
|
|
11424
|
+
);
|
|
11425
|
+
const href2 = (hrefEl instanceof HTMLAnchorElement ? hrefEl.getAttribute("href") : null) || hrefEl?.closest("a")?.getAttribute("href") || "/";
|
|
11426
|
+
return { text, isPlaceholder, imageUrl, href: href2, alt };
|
|
11427
|
+
}
|
|
11428
|
+
const logoRoot = document.querySelector('[data-ohw-role="logo"], [data-ohw-logo]');
|
|
11429
|
+
const href = (logoRoot instanceof HTMLAnchorElement ? logoRoot.getAttribute("href") : null) || logoRoot?.closest("a")?.getAttribute("href") || "/";
|
|
11430
|
+
return { text, isPlaceholder, imageUrl: null, href, alt: text };
|
|
11431
|
+
}
|
|
11432
|
+
function applyLogoFromContent(content) {
|
|
11433
|
+
const hasLogoIdentity = LOGO_PLACEHOLDER_KEY in content || LOGO_TEXT_KEYS.some((key) => key in content) || LOGO_IMAGE_KEYS.some((key) => key in content) || LOGO_ALT_KEY in content || LOGO_HREF_KEYS.some((key) => key in content);
|
|
11434
|
+
if (!hasLogoIdentity) return false;
|
|
11435
|
+
const logoText = content[LOGO_TEXT_KEYS[0]] ?? content[LOGO_TEXT_KEYS[1]] ?? readLogoIdentityFromDom().text;
|
|
11436
|
+
const logoAlt = content[LOGO_ALT_KEY] ?? logoText;
|
|
11437
|
+
const rawLogoImage = content[LOGO_IMAGE_URL_KEY] ?? content["footer-logo"] ?? content["footer-logo-image"] ?? null;
|
|
11438
|
+
const logoImageUrl = typeof rawLogoImage === "string" && rawLogoImage.trim() ? rawLogoImage.trim() : null;
|
|
11439
|
+
const imageExplicitlyCleared = LOGO_IMAGE_KEYS.some((key) => key in content) && !logoImageUrl;
|
|
11440
|
+
const logoIsPlaceholder = LOGO_PLACEHOLDER_KEY in content ? content[LOGO_PLACEHOLDER_KEY] !== "false" : !logoImageUrl && (!logoText.trim() || logoText === PLACEHOLDER_BUSINESS_NAME);
|
|
11441
|
+
if (logoImageUrl) {
|
|
11442
|
+
applyLogoImage(logoImageUrl, logoAlt);
|
|
11443
|
+
} else {
|
|
11444
|
+
if (imageExplicitlyCleared) applyLogoImage(null, logoAlt);
|
|
11445
|
+
applyLogoIdentity(logoText, logoIsPlaceholder);
|
|
11446
|
+
}
|
|
11447
|
+
const logoHref = content["nav-logo-href"] ?? content["footer-logo-href"] ?? content["logo-href"];
|
|
11448
|
+
if (typeof logoHref === "string" && logoHref.trim()) {
|
|
11449
|
+
applyLogoHref(logoHref);
|
|
11450
|
+
}
|
|
11451
|
+
return true;
|
|
11452
|
+
}
|
|
11453
|
+
|
|
11454
|
+
// src/lib/logo-size.ts
|
|
11455
|
+
var LOGO_SIZE_DEFAULTS = {
|
|
11456
|
+
navbar: 28,
|
|
11457
|
+
footer: 32
|
|
11458
|
+
};
|
|
11459
|
+
var LOGO_SIZE_MIN = 16;
|
|
11460
|
+
var LOGO_SIZE_MAX = 80;
|
|
11461
|
+
var LOGO_SIZE_DESKTOP_KEYS = {
|
|
11462
|
+
navbar: "nav-logo-size",
|
|
11463
|
+
footer: "footer-logo-size"
|
|
11464
|
+
};
|
|
11465
|
+
var LOGO_SIZE_MOBILE_KEYS = {
|
|
11466
|
+
navbar: "nav-logo-size-mobile",
|
|
11467
|
+
footer: "footer-logo-size-mobile"
|
|
11468
|
+
};
|
|
11469
|
+
var LOGO_SIZE_KEYS = [
|
|
11470
|
+
LOGO_SIZE_DESKTOP_KEYS.navbar,
|
|
11471
|
+
LOGO_SIZE_DESKTOP_KEYS.footer,
|
|
11472
|
+
LOGO_SIZE_MOBILE_KEYS.navbar,
|
|
11473
|
+
LOGO_SIZE_MOBILE_KEYS.footer
|
|
11474
|
+
];
|
|
11475
|
+
function isFooterLogoRoot2(root) {
|
|
11476
|
+
return Boolean(root.closest("footer") || root.closest('[data-ohw-section="footer"]'));
|
|
11477
|
+
}
|
|
11478
|
+
function getLogoPlacement(root) {
|
|
11479
|
+
return isFooterLogoRoot2(root) ? "footer" : "navbar";
|
|
11480
|
+
}
|
|
11481
|
+
function parseLogoSizePx(raw, fallback) {
|
|
11482
|
+
if (raw == null || raw === "") return fallback;
|
|
11483
|
+
const n = Number.parseFloat(raw);
|
|
11484
|
+
if (!Number.isFinite(n)) return fallback;
|
|
11485
|
+
return Math.min(LOGO_SIZE_MAX, Math.max(LOGO_SIZE_MIN, Math.round(n)));
|
|
11486
|
+
}
|
|
11487
|
+
function isMobileLogoSizeFollowing(content, placement) {
|
|
11488
|
+
const raw = content[LOGO_SIZE_MOBILE_KEYS[placement]];
|
|
11489
|
+
return raw == null || raw.trim() === "";
|
|
11490
|
+
}
|
|
11491
|
+
function resolveDesktopLogoSize(content, placement) {
|
|
11492
|
+
return parseLogoSizePx(content[LOGO_SIZE_DESKTOP_KEYS[placement]], LOGO_SIZE_DEFAULTS[placement]);
|
|
11493
|
+
}
|
|
11494
|
+
function resolveMobileLogoSize(content, placement) {
|
|
11495
|
+
if (isMobileLogoSizeFollowing(content, placement)) {
|
|
11496
|
+
return resolveDesktopLogoSize(content, placement);
|
|
11497
|
+
}
|
|
11498
|
+
return parseLogoSizePx(
|
|
11499
|
+
content[LOGO_SIZE_MOBILE_KEYS[placement]],
|
|
11500
|
+
resolveDesktopLogoSize(content, placement)
|
|
11501
|
+
);
|
|
11502
|
+
}
|
|
11503
|
+
function setRootSizeVars(root, desktopPx, mobilePx, following) {
|
|
11504
|
+
root.style.setProperty("--ohw-logo-size", `${desktopPx}px`);
|
|
11505
|
+
if (following) {
|
|
11506
|
+
root.style.removeProperty("--ohw-logo-size-mobile");
|
|
11507
|
+
} else {
|
|
11508
|
+
root.style.setProperty("--ohw-logo-size-mobile", `${mobilePx}px`);
|
|
11509
|
+
}
|
|
11510
|
+
root.querySelectorAll("img").forEach((img) => {
|
|
11511
|
+
img.style.height = "";
|
|
11512
|
+
img.style.maxHeight = "none";
|
|
11513
|
+
img.style.width = "auto";
|
|
11514
|
+
img.style.objectFit = "contain";
|
|
11515
|
+
});
|
|
11516
|
+
}
|
|
11517
|
+
function applyLogoSizes(content) {
|
|
11518
|
+
document.querySelectorAll('[data-ohw-role="logo"], [data-ohw-logo]').forEach((root) => {
|
|
11519
|
+
const placement = getLogoPlacement(root);
|
|
11520
|
+
const desktop = resolveDesktopLogoSize(content, placement);
|
|
11521
|
+
const following = isMobileLogoSizeFollowing(content, placement);
|
|
11522
|
+
const mobile = following ? desktop : resolveMobileLogoSize(content, placement);
|
|
11523
|
+
setRootSizeVars(root, desktop, mobile, following);
|
|
11524
|
+
});
|
|
11525
|
+
}
|
|
11526
|
+
function applyLogoSizeToPlacement(placement, desktopPx, mobilePx, following) {
|
|
11527
|
+
document.querySelectorAll('[data-ohw-role="logo"], [data-ohw-logo]').forEach((root) => {
|
|
11528
|
+
if (getLogoPlacement(root) !== placement) return;
|
|
11529
|
+
setRootSizeVars(root, desktopPx, mobilePx, following);
|
|
11530
|
+
});
|
|
11531
|
+
}
|
|
11532
|
+
function logoHasUploadedImage(logoEl) {
|
|
11533
|
+
if (logoEl.hasAttribute("data-ohw-placeholder")) return false;
|
|
11534
|
+
const img = logoEl.querySelector('img[data-ohw-key="nav-logo-image"], img[data-ohw-key="footer-logo"], img[data-ohw-key="footer-logo-image"]') ?? logoEl.querySelector("img");
|
|
11535
|
+
if (!img) return false;
|
|
11536
|
+
const src = img.getAttribute("src")?.trim() ?? "";
|
|
11537
|
+
if (!src || src.startsWith("data:")) return false;
|
|
11538
|
+
if (img.style.display === "none") return false;
|
|
11539
|
+
return true;
|
|
11540
|
+
}
|
|
11541
|
+
function getLogoInteractionRect(logoEl) {
|
|
11542
|
+
if (logoHasUploadedImage(logoEl)) {
|
|
11543
|
+
const img = logoEl.querySelector('img[data-ohw-key="nav-logo-image"], img[data-ohw-key="footer-logo"], img[data-ohw-key="footer-logo-image"]') ?? logoEl.querySelector("img");
|
|
11544
|
+
if (img) {
|
|
11545
|
+
const r2 = img.getBoundingClientRect();
|
|
11546
|
+
if (r2.width > 0 && r2.height > 0) return r2;
|
|
11547
|
+
}
|
|
11548
|
+
}
|
|
11549
|
+
const text = logoEl.querySelector(
|
|
11550
|
+
'[data-ohw-key="nav-logo-text"], [data-ohw-key="footer-logo-text"]'
|
|
11551
|
+
);
|
|
11552
|
+
if (text) {
|
|
11553
|
+
const style = window.getComputedStyle(text);
|
|
11554
|
+
if (style.display !== "none" && style.visibility !== "hidden") {
|
|
11555
|
+
const r2 = text.getBoundingClientRect();
|
|
11556
|
+
if (r2.width > 0 && r2.height > 0) return r2;
|
|
11557
|
+
}
|
|
11558
|
+
}
|
|
11559
|
+
return logoEl.getBoundingClientRect();
|
|
11560
|
+
}
|
|
11561
|
+
function readLogoSizeState(content, placement) {
|
|
11562
|
+
const desktopPx = resolveDesktopLogoSize(content, placement);
|
|
11563
|
+
const mobileFollowing = isMobileLogoSizeFollowing(content, placement);
|
|
11564
|
+
const mobilePx = mobileFollowing ? desktopPx : resolveMobileLogoSize(content, placement);
|
|
11565
|
+
return { desktopPx, mobilePx, mobileFollowing };
|
|
11566
|
+
}
|
|
11567
|
+
|
|
11568
|
+
// src/lib/site-wide-scope.ts
|
|
11569
|
+
function getLogoElement(el) {
|
|
11570
|
+
const marked = el.closest('[data-ohw-role="logo"], [data-ohw-logo]');
|
|
11571
|
+
if (marked) return marked;
|
|
11572
|
+
if (el.closest('[data-ohw-editable="icon"]')) return null;
|
|
11573
|
+
const root = el.closest("nav, [data-ohw-nav-root], footer");
|
|
11574
|
+
if (!root) return null;
|
|
11575
|
+
const anchor = el.closest("a");
|
|
11576
|
+
if (anchor && root.contains(anchor) && !anchor.hasAttribute("data-ohw-href-key") && !anchor.closest("[data-ohw-nav-container]") && Boolean(anchor.querySelector("img") || anchor.matches("img"))) {
|
|
11577
|
+
return anchor;
|
|
11578
|
+
}
|
|
11579
|
+
const img = el.matches("img") ? el : null;
|
|
11580
|
+
if (img && !img.closest("[data-ohw-href-key]") && !img.closest("[data-ohw-nav-container]") && (img.closest("footer") || img.closest("nav, [data-ohw-nav-root]"))) {
|
|
11581
|
+
return img;
|
|
11582
|
+
}
|
|
11583
|
+
return null;
|
|
11584
|
+
}
|
|
11585
|
+
function isInFooter(el) {
|
|
11586
|
+
if (!el) return false;
|
|
11587
|
+
return Boolean(el.closest("footer") || el.closest('[data-ohw-section="footer"]'));
|
|
11588
|
+
}
|
|
11589
|
+
function isSiteWideElement(el) {
|
|
11590
|
+
if (!el) return false;
|
|
11591
|
+
if (getLogoElement(el)) return true;
|
|
11592
|
+
if (isInFooter(el)) return true;
|
|
11593
|
+
if (el.hasAttribute("data-ohw-nav-container") || el.hasAttribute("data-ohw-nav-root")) {
|
|
11594
|
+
return true;
|
|
11595
|
+
}
|
|
11596
|
+
if (el.hasAttribute("data-ohw-href-key") && el.closest("nav, [data-ohw-nav-root], [data-ohw-nav-drawer], aside")) {
|
|
11597
|
+
return true;
|
|
11598
|
+
}
|
|
11599
|
+
if (el.closest('[data-ohw-role="navbar-button"]')) return true;
|
|
11600
|
+
return false;
|
|
11601
|
+
}
|
|
11602
|
+
function isSiteWideScopeActive(args) {
|
|
11603
|
+
return isSiteWideElement(args.selected) || isSiteWideElement(args.hoveredItem) || isSiteWideElement(args.hoveredNavContainer) || isSiteWideElement(args.active);
|
|
11604
|
+
}
|
|
11605
|
+
|
|
10893
11606
|
// src/lib/add-footer-column.ts
|
|
10894
11607
|
function buildFooterColumnEditContentPatch(result) {
|
|
10895
11608
|
return {
|
|
@@ -10995,6 +11708,7 @@ function FloatingPanel({
|
|
|
10995
11708
|
e.stopPropagation();
|
|
10996
11709
|
const el = e.currentTarget;
|
|
10997
11710
|
el.setPointerCapture(e.pointerId);
|
|
11711
|
+
document.documentElement.setAttribute("data-ohw-panel-dragging", "");
|
|
10998
11712
|
dragRef.current = {
|
|
10999
11713
|
pointerId: e.pointerId,
|
|
11000
11714
|
startX: e.clientX,
|
|
@@ -11027,11 +11741,17 @@ function FloatingPanel({
|
|
|
11027
11741
|
const drag = dragRef.current;
|
|
11028
11742
|
if (!drag || drag.pointerId !== e.pointerId) return;
|
|
11029
11743
|
dragRef.current = null;
|
|
11744
|
+
document.documentElement.removeAttribute("data-ohw-panel-dragging");
|
|
11030
11745
|
try {
|
|
11031
11746
|
e.currentTarget.releasePointerCapture(e.pointerId);
|
|
11032
11747
|
} catch {
|
|
11033
11748
|
}
|
|
11034
11749
|
}, []);
|
|
11750
|
+
(0, import_react13.useEffect)(() => {
|
|
11751
|
+
if (open) return;
|
|
11752
|
+
document.documentElement.removeAttribute("data-ohw-panel-dragging");
|
|
11753
|
+
}, [open]);
|
|
11754
|
+
(0, import_react13.useEffect)(() => () => document.documentElement.removeAttribute("data-ohw-panel-dragging"), []);
|
|
11035
11755
|
if (!open) return null;
|
|
11036
11756
|
return /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)(
|
|
11037
11757
|
"div",
|
|
@@ -11098,16 +11818,127 @@ function FloatingPanel({
|
|
|
11098
11818
|
);
|
|
11099
11819
|
}
|
|
11100
11820
|
|
|
11101
|
-
// src/ui/
|
|
11821
|
+
// src/ui/logo-size-panel.tsx
|
|
11822
|
+
var import_lucide_react14 = require("lucide-react");
|
|
11102
11823
|
var import_jsx_runtime27 = require("react/jsx-runtime");
|
|
11824
|
+
function SizeSlider({
|
|
11825
|
+
value,
|
|
11826
|
+
onChange
|
|
11827
|
+
}) {
|
|
11828
|
+
const pct = (value - LOGO_SIZE_MIN) / (LOGO_SIZE_MAX - LOGO_SIZE_MIN) * 100;
|
|
11829
|
+
return /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("div", { className: "flex w-full flex-col gap-3", children: [
|
|
11830
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("div", { className: "flex w-full items-center gap-2 text-sm font-medium leading-5", children: [
|
|
11831
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsx)("span", { className: "min-w-0 flex-1 text-foreground", children: "Size" }),
|
|
11832
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("span", { className: "shrink-0 whitespace-nowrap text-muted-foreground", children: [
|
|
11833
|
+
value,
|
|
11834
|
+
" px"
|
|
11835
|
+
] })
|
|
11836
|
+
] }),
|
|
11837
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("div", { className: "relative h-2 w-full rounded-full bg-primary-50", children: [
|
|
11838
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
|
|
11839
|
+
"div",
|
|
11840
|
+
{
|
|
11841
|
+
className: "absolute inset-y-0 left-0 rounded-full bg-primary",
|
|
11842
|
+
style: { width: `${pct}%` }
|
|
11843
|
+
}
|
|
11844
|
+
),
|
|
11845
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
|
|
11846
|
+
"input",
|
|
11847
|
+
{
|
|
11848
|
+
type: "range",
|
|
11849
|
+
min: LOGO_SIZE_MIN,
|
|
11850
|
+
max: LOGO_SIZE_MAX,
|
|
11851
|
+
step: 1,
|
|
11852
|
+
value,
|
|
11853
|
+
"aria-label": "Logo size",
|
|
11854
|
+
className: cn(
|
|
11855
|
+
"absolute inset-0 h-full w-full cursor-pointer appearance-none bg-transparent",
|
|
11856
|
+
"[&::-webkit-slider-thumb]:appearance-none [&::-webkit-slider-thumb]:size-5",
|
|
11857
|
+
"[&::-webkit-slider-thumb]:rounded-full [&::-webkit-slider-thumb]:border-2",
|
|
11858
|
+
"[&::-webkit-slider-thumb]:border-primary [&::-webkit-slider-thumb]:bg-background",
|
|
11859
|
+
"[&::-moz-range-thumb]:size-5 [&::-moz-range-thumb]:rounded-full",
|
|
11860
|
+
"[&::-moz-range-thumb]:border-2 [&::-moz-range-thumb]:border-primary",
|
|
11861
|
+
"[&::-moz-range-thumb]:bg-background"
|
|
11862
|
+
),
|
|
11863
|
+
onChange: (e) => onChange(Number(e.target.value))
|
|
11864
|
+
}
|
|
11865
|
+
)
|
|
11866
|
+
] })
|
|
11867
|
+
] });
|
|
11868
|
+
}
|
|
11869
|
+
function LogoSizePanel({
|
|
11870
|
+
viewport,
|
|
11871
|
+
sizePx,
|
|
11872
|
+
mobileFollowing = true,
|
|
11873
|
+
onSizeChange,
|
|
11874
|
+
onCustomizeMobile,
|
|
11875
|
+
onResetMobile,
|
|
11876
|
+
onUpdateEverywhere,
|
|
11877
|
+
className
|
|
11878
|
+
}) {
|
|
11879
|
+
const showFollowing = viewport === "mobile" && mobileFollowing;
|
|
11880
|
+
const showMobileSlider = viewport === "mobile" && !mobileFollowing;
|
|
11881
|
+
const showDesktopSlider = viewport === "desktop";
|
|
11882
|
+
return /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("div", { className: cn("flex w-full flex-col gap-4", className), children: [
|
|
11883
|
+
showFollowing ? /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("div", { className: "flex w-full flex-col gap-2", children: [
|
|
11884
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("div", { className: "flex items-start gap-1", children: [
|
|
11885
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsx)(import_lucide_react14.Link, { size: 16, className: "mt-0.5 shrink-0 text-foreground", "aria-hidden": true }),
|
|
11886
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsx)("p", { className: "text-sm font-semibold leading-5 text-foreground", children: "Following desktop size" })
|
|
11887
|
+
] }),
|
|
11888
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsx)("p", { className: "text-sm leading-5 text-muted-foreground", children: "Mobile uses the desktop size until you customize it. Change the desktop size and it follows automatically." }),
|
|
11889
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
|
|
11890
|
+
Button,
|
|
11891
|
+
{
|
|
11892
|
+
type: "button",
|
|
11893
|
+
variant: "outline",
|
|
11894
|
+
size: "sm",
|
|
11895
|
+
className: "h-9 w-full min-w-0 cursor-pointer",
|
|
11896
|
+
onClick: onCustomizeMobile,
|
|
11897
|
+
children: "Customize for mobile"
|
|
11898
|
+
}
|
|
11899
|
+
)
|
|
11900
|
+
] }) : null,
|
|
11901
|
+
showDesktopSlider || showMobileSlider ? /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(SizeSlider, { value: sizePx, onChange: onSizeChange }) : null,
|
|
11902
|
+
showMobileSlider ? /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
|
|
11903
|
+
Button,
|
|
11904
|
+
{
|
|
11905
|
+
type: "button",
|
|
11906
|
+
variant: "outline",
|
|
11907
|
+
size: "sm",
|
|
11908
|
+
className: "h-9 w-full min-w-0 cursor-pointer",
|
|
11909
|
+
onClick: onResetMobile,
|
|
11910
|
+
children: "Reset to desktop size"
|
|
11911
|
+
}
|
|
11912
|
+
) : null,
|
|
11913
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsx)("div", { className: "h-px w-full bg-border", role: "separator" }),
|
|
11914
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsxs)(
|
|
11915
|
+
Button,
|
|
11916
|
+
{
|
|
11917
|
+
type: "button",
|
|
11918
|
+
variant: "outline",
|
|
11919
|
+
size: "sm",
|
|
11920
|
+
className: "h-9 w-full min-w-0 cursor-pointer gap-1",
|
|
11921
|
+
onClick: onUpdateEverywhere,
|
|
11922
|
+
children: [
|
|
11923
|
+
"Update logo everywhere",
|
|
11924
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsx)(import_lucide_react14.ArrowUpRight, { size: 16, "aria-hidden": true })
|
|
11925
|
+
]
|
|
11926
|
+
}
|
|
11927
|
+
),
|
|
11928
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsx)("p", { className: "text-sm leading-5 text-muted-foreground", children: "Matches the right version to your background." })
|
|
11929
|
+
] });
|
|
11930
|
+
}
|
|
11931
|
+
|
|
11932
|
+
// src/ui/socials-display-panel.tsx
|
|
11933
|
+
var import_jsx_runtime28 = require("react/jsx-runtime");
|
|
11103
11934
|
function DisplaySwitch({
|
|
11104
11935
|
label,
|
|
11105
11936
|
checked,
|
|
11106
11937
|
disabled,
|
|
11107
11938
|
onChange
|
|
11108
11939
|
}) {
|
|
11109
|
-
return /* @__PURE__ */ (0,
|
|
11110
|
-
/* @__PURE__ */ (0,
|
|
11940
|
+
return /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)("div", { className: "flex w-full items-center gap-2", children: [
|
|
11941
|
+
/* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
|
|
11111
11942
|
"span",
|
|
11112
11943
|
{
|
|
11113
11944
|
className: cn(
|
|
@@ -11117,7 +11948,7 @@ function DisplaySwitch({
|
|
|
11117
11948
|
children: label
|
|
11118
11949
|
}
|
|
11119
11950
|
),
|
|
11120
|
-
/* @__PURE__ */ (0,
|
|
11951
|
+
/* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
|
|
11121
11952
|
"button",
|
|
11122
11953
|
{
|
|
11123
11954
|
type: "button",
|
|
@@ -11131,7 +11962,7 @@ function DisplaySwitch({
|
|
|
11131
11962
|
checked ? "bg-primary" : "bg-primary-50",
|
|
11132
11963
|
disabled ? "cursor-default opacity-50" : "cursor-pointer"
|
|
11133
11964
|
),
|
|
11134
|
-
children: /* @__PURE__ */ (0,
|
|
11965
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
|
|
11135
11966
|
"span",
|
|
11136
11967
|
{
|
|
11137
11968
|
className: cn(
|
|
@@ -11145,8 +11976,8 @@ function DisplaySwitch({
|
|
|
11145
11976
|
] });
|
|
11146
11977
|
}
|
|
11147
11978
|
function SocialsDisplayPanel({ display, onChange, className }) {
|
|
11148
|
-
return /* @__PURE__ */ (0,
|
|
11149
|
-
/* @__PURE__ */ (0,
|
|
11979
|
+
return /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)("div", { className: cn("flex w-full flex-col gap-3", className), children: [
|
|
11980
|
+
/* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
|
|
11150
11981
|
DisplaySwitch,
|
|
11151
11982
|
{
|
|
11152
11983
|
label: "Text",
|
|
@@ -11155,7 +11986,7 @@ function SocialsDisplayPanel({ display, onChange, className }) {
|
|
|
11155
11986
|
onChange: (text) => onChange({ ...display, text })
|
|
11156
11987
|
}
|
|
11157
11988
|
),
|
|
11158
|
-
/* @__PURE__ */ (0,
|
|
11989
|
+
/* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
|
|
11159
11990
|
DisplaySwitch,
|
|
11160
11991
|
{
|
|
11161
11992
|
label: "Icon",
|
|
@@ -11715,8 +12546,8 @@ function useNavItemDrag({
|
|
|
11715
12546
|
}
|
|
11716
12547
|
|
|
11717
12548
|
// src/ui/footer-container-chrome.tsx
|
|
11718
|
-
var
|
|
11719
|
-
var
|
|
12549
|
+
var import_lucide_react15 = require("lucide-react");
|
|
12550
|
+
var import_jsx_runtime29 = require("react/jsx-runtime");
|
|
11720
12551
|
function FooterContainerChrome({
|
|
11721
12552
|
rect,
|
|
11722
12553
|
onAdd,
|
|
@@ -11724,7 +12555,7 @@ function FooterContainerChrome({
|
|
|
11724
12555
|
}) {
|
|
11725
12556
|
const chromeGap = 6;
|
|
11726
12557
|
const buttonMargin = 7;
|
|
11727
|
-
return /* @__PURE__ */ (0,
|
|
12558
|
+
return /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(TooltipProvider, { delayDuration: 0, children: /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
|
|
11728
12559
|
"div",
|
|
11729
12560
|
{
|
|
11730
12561
|
"data-ohw-footer-container-chrome": "",
|
|
@@ -11736,8 +12567,8 @@ function FooterContainerChrome({
|
|
|
11736
12567
|
width: rect.width + chromeGap * 2,
|
|
11737
12568
|
height: rect.height + chromeGap * 2
|
|
11738
12569
|
},
|
|
11739
|
-
children: /* @__PURE__ */ (0,
|
|
11740
|
-
/* @__PURE__ */ (0,
|
|
12570
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)(Tooltip, { children: [
|
|
12571
|
+
/* @__PURE__ */ (0, import_jsx_runtime29.jsx)(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
|
|
11741
12572
|
"button",
|
|
11742
12573
|
{
|
|
11743
12574
|
type: "button",
|
|
@@ -11756,10 +12587,10 @@ function FooterContainerChrome({
|
|
|
11756
12587
|
if (addDisabled) return;
|
|
11757
12588
|
onAdd();
|
|
11758
12589
|
},
|
|
11759
|
-
children: /* @__PURE__ */ (0,
|
|
12590
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(import_lucide_react15.Plus, { className: "size-4 shrink-0 text-foreground", "aria-hidden": true })
|
|
11760
12591
|
}
|
|
11761
12592
|
) }),
|
|
11762
|
-
/* @__PURE__ */ (0,
|
|
12593
|
+
/* @__PURE__ */ (0, import_jsx_runtime29.jsx)(TooltipContent, { side: "bottom", sideOffset: 9, children: addDisabled ? "Maximum columns reached" : "Add item" })
|
|
11763
12594
|
] })
|
|
11764
12595
|
}
|
|
11765
12596
|
) });
|
|
@@ -11942,6 +12773,18 @@ function collectEditableNodes(extraContent, root = document) {
|
|
|
11942
12773
|
}
|
|
11943
12774
|
if (extraContent && !isScoped) {
|
|
11944
12775
|
applyNavFooterDeleteOverrides(byKey, extraContent);
|
|
12776
|
+
for (const key of LOGO_IMAGE_KEYS) {
|
|
12777
|
+
if (!(key in extraContent)) continue;
|
|
12778
|
+
byKey.set(key, { key, type: "image", text: extraContent[key] ?? "" });
|
|
12779
|
+
}
|
|
12780
|
+
for (const key of [LOGO_PLACEHOLDER_KEY, LOGO_ALT_KEY]) {
|
|
12781
|
+
if (!(key in extraContent)) continue;
|
|
12782
|
+
byKey.set(key, { key, type: "meta", text: extraContent[key] ?? "" });
|
|
12783
|
+
}
|
|
12784
|
+
for (const key of LOGO_SIZE_KEYS) {
|
|
12785
|
+
if (!(key in extraContent)) continue;
|
|
12786
|
+
byKey.set(key, { key, type: "meta", text: extraContent[key] ?? "" });
|
|
12787
|
+
}
|
|
11945
12788
|
}
|
|
11946
12789
|
return Array.from(byKey.values());
|
|
11947
12790
|
}
|
|
@@ -12207,14 +13050,14 @@ function deleteSelectedNavFooterItem(deps) {
|
|
|
12207
13050
|
}
|
|
12208
13051
|
|
|
12209
13052
|
// src/ui/navbar-container-chrome.tsx
|
|
12210
|
-
var
|
|
12211
|
-
var
|
|
13053
|
+
var import_lucide_react16 = require("lucide-react");
|
|
13054
|
+
var import_jsx_runtime30 = require("react/jsx-runtime");
|
|
12212
13055
|
function NavbarContainerChrome({
|
|
12213
13056
|
rect,
|
|
12214
13057
|
onAdd
|
|
12215
13058
|
}) {
|
|
12216
13059
|
const chromeGap = 6;
|
|
12217
|
-
return /* @__PURE__ */ (0,
|
|
13060
|
+
return /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
|
|
12218
13061
|
"div",
|
|
12219
13062
|
{
|
|
12220
13063
|
"data-ohw-navbar-container-chrome": "",
|
|
@@ -12226,7 +13069,7 @@ function NavbarContainerChrome({
|
|
|
12226
13069
|
width: rect.width + chromeGap * 2,
|
|
12227
13070
|
height: rect.height + chromeGap * 2
|
|
12228
13071
|
},
|
|
12229
|
-
children: /* @__PURE__ */ (0,
|
|
13072
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
|
|
12230
13073
|
"button",
|
|
12231
13074
|
{
|
|
12232
13075
|
type: "button",
|
|
@@ -12243,7 +13086,7 @@ function NavbarContainerChrome({
|
|
|
12243
13086
|
e.stopPropagation();
|
|
12244
13087
|
onAdd();
|
|
12245
13088
|
},
|
|
12246
|
-
children: /* @__PURE__ */ (0,
|
|
13089
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(import_lucide_react16.Plus, { className: "size-4 shrink-0 text-foreground", "aria-hidden": true })
|
|
12247
13090
|
}
|
|
12248
13091
|
)
|
|
12249
13092
|
}
|
|
@@ -12252,7 +13095,7 @@ function NavbarContainerChrome({
|
|
|
12252
13095
|
|
|
12253
13096
|
// src/ui/drop-indicator.tsx
|
|
12254
13097
|
var React10 = __toESM(require("react"), 1);
|
|
12255
|
-
var
|
|
13098
|
+
var import_jsx_runtime31 = require("react/jsx-runtime");
|
|
12256
13099
|
var dropIndicatorVariants = cva(
|
|
12257
13100
|
"ov-gap-line pointer-events-none shrink-0 transition-opacity duration-150",
|
|
12258
13101
|
{
|
|
@@ -12276,7 +13119,7 @@ var dropIndicatorVariants = cva(
|
|
|
12276
13119
|
);
|
|
12277
13120
|
var DropIndicator = React10.forwardRef(
|
|
12278
13121
|
({ className, direction, state, ...props }, ref) => {
|
|
12279
|
-
return /* @__PURE__ */ (0,
|
|
13122
|
+
return /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(
|
|
12280
13123
|
"div",
|
|
12281
13124
|
{
|
|
12282
13125
|
ref,
|
|
@@ -12293,7 +13136,7 @@ var DropIndicator = React10.forwardRef(
|
|
|
12293
13136
|
DropIndicator.displayName = "DropIndicator";
|
|
12294
13137
|
|
|
12295
13138
|
// src/ui/badge.tsx
|
|
12296
|
-
var
|
|
13139
|
+
var import_jsx_runtime32 = require("react/jsx-runtime");
|
|
12297
13140
|
var badgeVariants = cva(
|
|
12298
13141
|
"inline-flex items-center rounded-full border px-2.5 py-0.5 text-xs font-semibold transition-colors focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2",
|
|
12299
13142
|
{
|
|
@@ -12311,12 +13154,12 @@ var badgeVariants = cva(
|
|
|
12311
13154
|
}
|
|
12312
13155
|
);
|
|
12313
13156
|
function Badge({ className, variant, ...props }) {
|
|
12314
|
-
return /* @__PURE__ */ (0,
|
|
13157
|
+
return /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("div", { className: cn(badgeVariants({ variant }), className), ...props });
|
|
12315
13158
|
}
|
|
12316
13159
|
|
|
12317
13160
|
// src/OhhwellsBridge.tsx
|
|
12318
|
-
var
|
|
12319
|
-
var
|
|
13161
|
+
var import_lucide_react17 = require("lucide-react");
|
|
13162
|
+
var import_jsx_runtime33 = require("react/jsx-runtime");
|
|
12320
13163
|
var PRIMARY3 = "#0885FE";
|
|
12321
13164
|
var IMAGE_FADE_MS = 300;
|
|
12322
13165
|
function runOpacityFade(el, onDone) {
|
|
@@ -12410,21 +13253,10 @@ function parseSchedulingInsertAfter(insertAfter) {
|
|
|
12410
13253
|
insertBefore: insertAfter.slice(idx + INSERT_BEFORE_MARKER.length)
|
|
12411
13254
|
};
|
|
12412
13255
|
}
|
|
12413
|
-
function
|
|
12414
|
-
|
|
12415
|
-
const
|
|
12416
|
-
|
|
12417
|
-
return { effectiveInsertAfter, insertBefore };
|
|
12418
|
-
}
|
|
12419
|
-
function getSchedulingMountPoint(insertAfter) {
|
|
12420
|
-
const { anchor } = parseSchedulingInsertAfter(insertAfter);
|
|
12421
|
-
let anchorEl = document.querySelector(`[data-ohw-section="${anchor}"]`);
|
|
12422
|
-
if (!anchorEl && anchor === "scheduling") {
|
|
12423
|
-
const widgets = Array.from(document.querySelectorAll('[data-ohw-section^="scheduling-"]'));
|
|
12424
|
-
anchorEl = widgets.at(-1) ?? null;
|
|
12425
|
-
}
|
|
12426
|
-
if (!anchorEl) return null;
|
|
12427
|
-
return anchorEl.closest('[data-ohw-section-container="scheduling"]') ?? anchorEl;
|
|
13256
|
+
function resolveEntryAnchor(entry) {
|
|
13257
|
+
if (entry.anchorId !== void 0) return { anchorId: entry.anchorId, beforeId: entry.beforeId ?? null };
|
|
13258
|
+
const parsed = parseSchedulingInsertAfter(entry.insertAfter);
|
|
13259
|
+
return { anchorId: parsed.anchor, beforeId: parsed.insertBefore };
|
|
12428
13260
|
}
|
|
12429
13261
|
function schedulingMountDepth(insertAfter) {
|
|
12430
13262
|
if (!insertAfter.includes(INSERT_BEFORE_MARKER)) return 0;
|
|
@@ -12441,8 +13273,7 @@ function getPageSchedulingEntries(raw) {
|
|
|
12441
13273
|
}
|
|
12442
13274
|
}
|
|
12443
13275
|
function isSchedulingWidgetMissing(entry) {
|
|
12444
|
-
|
|
12445
|
-
return !document.querySelector(`[data-ohw-section="${schedulingSectionId(effectiveInsertAfter)}"]`);
|
|
13276
|
+
return !document.querySelector(`[data-ohw-section="${schedulingSectionId(entry.insertAfter)}"]`);
|
|
12446
13277
|
}
|
|
12447
13278
|
function hasMissingSchedulingWidgets(entries) {
|
|
12448
13279
|
return entries.some(isSchedulingWidgetMissing);
|
|
@@ -12472,16 +13303,17 @@ function initSectionsFromContent(content, removeExisting = false) {
|
|
|
12472
13303
|
} catch {
|
|
12473
13304
|
}
|
|
12474
13305
|
}
|
|
12475
|
-
function mountSchedulingWidget(
|
|
12476
|
-
const
|
|
12477
|
-
const sectionId = schedulingSectionId(
|
|
13306
|
+
function mountSchedulingWidget(anchorId, notifyOnConnect = false, scheduleId, beforeId, existingWidgetId) {
|
|
13307
|
+
const widgetId = existingWidgetId ?? (beforeId ? `${anchorId}${INSERT_BEFORE_MARKER}${beforeId}` : anchorId);
|
|
13308
|
+
const sectionId = schedulingSectionId(widgetId);
|
|
12478
13309
|
if (document.querySelector(`[data-ohw-section="${sectionId}"]`)) return false;
|
|
12479
|
-
const
|
|
12480
|
-
if (!
|
|
13310
|
+
const anchorEl = document.querySelector(`[data-ohw-section="${anchorId}"]`);
|
|
13311
|
+
if (!anchorEl) return false;
|
|
13312
|
+
const mountPoint = anchorEl.closest('[data-ohw-section-container="scheduling"]') ?? anchorEl;
|
|
12481
13313
|
const container = document.createElement("div");
|
|
12482
13314
|
container.dataset.ohwSectionContainer = "scheduling";
|
|
12483
|
-
if (
|
|
12484
|
-
const beforeAnchor = document.querySelector(`[data-ohw-section="${
|
|
13315
|
+
if (beforeId) {
|
|
13316
|
+
const beforeAnchor = document.querySelector(`[data-ohw-section="${beforeId}"]`);
|
|
12485
13317
|
const beforePoint = beforeAnchor?.closest('[data-ohw-section-container="scheduling"]') ?? beforeAnchor;
|
|
12486
13318
|
if (!beforePoint) return false;
|
|
12487
13319
|
beforePoint.insertAdjacentElement("beforebegin", container);
|
|
@@ -12492,19 +13324,25 @@ function mountSchedulingWidget(insertAfter, notifyOnConnect = false, scheduleId,
|
|
|
12492
13324
|
}
|
|
12493
13325
|
tail.insertAdjacentElement("afterend", container);
|
|
12494
13326
|
}
|
|
12495
|
-
|
|
12496
|
-
|
|
12497
|
-
|
|
12498
|
-
|
|
12499
|
-
|
|
12500
|
-
|
|
12501
|
-
|
|
12502
|
-
|
|
12503
|
-
|
|
12504
|
-
|
|
12505
|
-
|
|
12506
|
-
|
|
12507
|
-
|
|
13327
|
+
try {
|
|
13328
|
+
const root = (0, import_client2.createRoot)(container);
|
|
13329
|
+
(0, import_react_dom3.flushSync)(() => {
|
|
13330
|
+
root.render(
|
|
13331
|
+
/* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
|
|
13332
|
+
SchedulingWidget,
|
|
13333
|
+
{
|
|
13334
|
+
notifyOnConnect,
|
|
13335
|
+
initialScheduleId: scheduleId,
|
|
13336
|
+
insertAfter: widgetId
|
|
13337
|
+
}
|
|
13338
|
+
)
|
|
13339
|
+
);
|
|
13340
|
+
});
|
|
13341
|
+
} catch (err) {
|
|
13342
|
+
console.error("[ow:scheduling] render threw", err);
|
|
13343
|
+
container.remove();
|
|
13344
|
+
return false;
|
|
13345
|
+
}
|
|
12508
13346
|
const tracker = getSectionsTracker();
|
|
12509
13347
|
let sections = [];
|
|
12510
13348
|
try {
|
|
@@ -12512,10 +13350,12 @@ function mountSchedulingWidget(insertAfter, notifyOnConnect = false, scheduleId,
|
|
|
12512
13350
|
} catch {
|
|
12513
13351
|
}
|
|
12514
13352
|
const inEditor = typeof window !== "undefined" && window.self !== window.top;
|
|
12515
|
-
if (inEditor && !sections.find((s) => s.type === "scheduling" && s.insertAfter ===
|
|
13353
|
+
if (inEditor && !sections.find((s) => s.type === "scheduling" && s.insertAfter === widgetId)) {
|
|
12516
13354
|
sections.push({
|
|
12517
13355
|
type: "scheduling",
|
|
12518
|
-
insertAfter:
|
|
13356
|
+
insertAfter: widgetId,
|
|
13357
|
+
anchorId,
|
|
13358
|
+
beforeId: beforeId ?? null,
|
|
12519
13359
|
pagePath: window.location.pathname,
|
|
12520
13360
|
...scheduleId ? { scheduleId } : {}
|
|
12521
13361
|
});
|
|
@@ -12529,7 +13369,8 @@ function mountSchedulingEntries(entries, notifyOnConnect = false) {
|
|
|
12529
13369
|
for (let i = pending.length - 1; i >= 0; i--) {
|
|
12530
13370
|
const entry = pending[i];
|
|
12531
13371
|
const shouldNotify = typeof notifyOnConnect === "function" ? notifyOnConnect(entry) : notifyOnConnect;
|
|
12532
|
-
|
|
13372
|
+
const { anchorId, beforeId } = resolveEntryAnchor(entry);
|
|
13373
|
+
if (mountSchedulingWidget(anchorId, shouldNotify, entry.scheduleId ?? null, beforeId, entry.insertAfter)) {
|
|
12533
13374
|
pending.splice(i, 1);
|
|
12534
13375
|
}
|
|
12535
13376
|
}
|
|
@@ -12673,6 +13514,13 @@ function isInsideLinkEditor(target) {
|
|
|
12673
13514
|
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"]')
|
|
12674
13515
|
);
|
|
12675
13516
|
}
|
|
13517
|
+
function isInsideFloatingPanel(target) {
|
|
13518
|
+
return Boolean(target.closest("[data-ohw-floating-panel]"));
|
|
13519
|
+
}
|
|
13520
|
+
function isPointOverFloatingPanel(clientX, clientY) {
|
|
13521
|
+
const el = document.elementFromPoint(clientX, clientY);
|
|
13522
|
+
return Boolean(el instanceof Element && el.closest("[data-ohw-floating-panel]"));
|
|
13523
|
+
}
|
|
12676
13524
|
function getHrefKeyFromElement(el) {
|
|
12677
13525
|
if (!el) return null;
|
|
12678
13526
|
const anchor = el.closest("[data-ohw-href-key]");
|
|
@@ -12810,6 +13658,11 @@ function isNavbarLinksContainer2(el) {
|
|
|
12810
13658
|
function getFooterColumn(el) {
|
|
12811
13659
|
return el.closest("[data-ohw-footer-col], [data-ohw-footer-column]");
|
|
12812
13660
|
}
|
|
13661
|
+
function isFooterAddItemDisabled(selected) {
|
|
13662
|
+
if (!selected) return false;
|
|
13663
|
+
const column = resolveFooterColumnForAdd(selected);
|
|
13664
|
+
return column ? !canAddFooterItem(column) : false;
|
|
13665
|
+
}
|
|
12813
13666
|
function resolveFooterColumnSelectionTarget(target, clientX, clientY) {
|
|
12814
13667
|
if (getNavigationItemAnchor(target)) return null;
|
|
12815
13668
|
const column = getFooterColumn(target);
|
|
@@ -12905,7 +13758,7 @@ function getNavigationSelectionParent(el) {
|
|
|
12905
13758
|
if (!isFooterLinksContainer(el) && (el.hasAttribute("data-ohw-footer-col") || el.hasAttribute("data-ohw-footer-column") || isInferredFooterGroup2(el))) {
|
|
12906
13759
|
return getFooterLinksContainer();
|
|
12907
13760
|
}
|
|
12908
|
-
if (el.hasAttribute("data-ohw-nav-container") || el.hasAttribute("data-ohw-nav-drawer") || isFooterLinksContainer(el)) {
|
|
13761
|
+
if (el.hasAttribute("data-ohw-nav-container") || el.hasAttribute("data-ohw-nav-drawer") || el.hasAttribute("data-ohw-footer-col") || el.hasAttribute("data-ohw-footer-column") || isFooterLinksContainer(el) || isInferredFooterGroup2(el)) {
|
|
12909
13762
|
return getNavigationRoot(el);
|
|
12910
13763
|
}
|
|
12911
13764
|
return null;
|
|
@@ -13123,6 +13976,9 @@ var ICONS = {
|
|
|
13123
13976
|
var SELECTION_CHROME_GAP2 = 4;
|
|
13124
13977
|
var TOOLBAR_STROKE_GAP2 = 4;
|
|
13125
13978
|
var TOOLBAR_OFFSET_FROM_ELEMENT = SELECTION_CHROME_GAP2 + TOOLBAR_STROKE_GAP2;
|
|
13979
|
+
var HOVER_STROKE_WIDTH = 1.5;
|
|
13980
|
+
var TEXT_HOVER_SIDE_PAD = 4;
|
|
13981
|
+
var CHROME_PRIMARY = `var(--ohw-primary, ${PRIMARY3})`;
|
|
13126
13982
|
var TOOLBAR_GROUPS = [
|
|
13127
13983
|
[
|
|
13128
13984
|
{ cmd: "bold", title: "Bold" },
|
|
@@ -13148,7 +14004,7 @@ function EditGlowChrome({
|
|
|
13148
14004
|
hideHandle = false
|
|
13149
14005
|
}) {
|
|
13150
14006
|
const GAP = SELECTION_CHROME_GAP2;
|
|
13151
|
-
return /* @__PURE__ */ (0,
|
|
14007
|
+
return /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)(
|
|
13152
14008
|
"div",
|
|
13153
14009
|
{
|
|
13154
14010
|
ref: elRef,
|
|
@@ -13163,7 +14019,7 @@ function EditGlowChrome({
|
|
|
13163
14019
|
zIndex: 2147483646
|
|
13164
14020
|
},
|
|
13165
14021
|
children: [
|
|
13166
|
-
/* @__PURE__ */ (0,
|
|
14022
|
+
/* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
|
|
13167
14023
|
"div",
|
|
13168
14024
|
{
|
|
13169
14025
|
style: {
|
|
@@ -13176,7 +14032,7 @@ function EditGlowChrome({
|
|
|
13176
14032
|
}
|
|
13177
14033
|
}
|
|
13178
14034
|
),
|
|
13179
|
-
reorderHrefKey && !hideHandle && /* @__PURE__ */ (0,
|
|
14035
|
+
reorderHrefKey && !hideHandle && /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
|
|
13180
14036
|
"div",
|
|
13181
14037
|
{
|
|
13182
14038
|
"data-ohw-drag-handle-container": "",
|
|
@@ -13188,7 +14044,7 @@ function EditGlowChrome({
|
|
|
13188
14044
|
transform: "translate(calc(-100% - 7px), -50%)",
|
|
13189
14045
|
pointerEvents: dragDisabled ? "none" : "auto"
|
|
13190
14046
|
},
|
|
13191
|
-
children: /* @__PURE__ */ (0,
|
|
14047
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
|
|
13192
14048
|
DragHandle,
|
|
13193
14049
|
{
|
|
13194
14050
|
"aria-label": `Reorder ${reorderHrefKey}`,
|
|
@@ -13398,7 +14254,7 @@ function FloatingToolbar({
|
|
|
13398
14254
|
return () => ro.disconnect();
|
|
13399
14255
|
}, [showEditLink, activeCommands]);
|
|
13400
14256
|
const { top, left, transform } = calcToolbarPos(rect, parentScroll, measuredW);
|
|
13401
|
-
return /* @__PURE__ */ (0,
|
|
14257
|
+
return /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
|
|
13402
14258
|
"div",
|
|
13403
14259
|
{
|
|
13404
14260
|
ref: setRefs,
|
|
@@ -13410,12 +14266,12 @@ function FloatingToolbar({
|
|
|
13410
14266
|
zIndex: 2147483647,
|
|
13411
14267
|
pointerEvents: "auto"
|
|
13412
14268
|
},
|
|
13413
|
-
children: /* @__PURE__ */ (0,
|
|
13414
|
-
TOOLBAR_GROUPS.map((btns, gi) => /* @__PURE__ */ (0,
|
|
13415
|
-
gi > 0 && /* @__PURE__ */ (0,
|
|
14269
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)(CustomToolbar, { children: [
|
|
14270
|
+
TOOLBAR_GROUPS.map((btns, gi) => /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)(import_react16.default.Fragment, { children: [
|
|
14271
|
+
gi > 0 && /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(CustomToolbarDivider, {}),
|
|
13416
14272
|
btns.map((btn) => {
|
|
13417
14273
|
const isActive = activeCommands.has(btn.cmd);
|
|
13418
|
-
return /* @__PURE__ */ (0,
|
|
14274
|
+
return /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
|
|
13419
14275
|
CustomToolbarButton,
|
|
13420
14276
|
{
|
|
13421
14277
|
title: btn.title,
|
|
@@ -13424,7 +14280,7 @@ function FloatingToolbar({
|
|
|
13424
14280
|
e.preventDefault();
|
|
13425
14281
|
onCommand(btn.cmd);
|
|
13426
14282
|
},
|
|
13427
|
-
children: /* @__PURE__ */ (0,
|
|
14283
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
|
|
13428
14284
|
"svg",
|
|
13429
14285
|
{
|
|
13430
14286
|
width: "16",
|
|
@@ -13445,7 +14301,7 @@ function FloatingToolbar({
|
|
|
13445
14301
|
);
|
|
13446
14302
|
})
|
|
13447
14303
|
] }, gi)),
|
|
13448
|
-
showEditLink ? /* @__PURE__ */ (0,
|
|
14304
|
+
showEditLink ? /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
|
|
13449
14305
|
CustomToolbarButton,
|
|
13450
14306
|
{
|
|
13451
14307
|
type: "button",
|
|
@@ -13459,7 +14315,7 @@ function FloatingToolbar({
|
|
|
13459
14315
|
e.preventDefault();
|
|
13460
14316
|
e.stopPropagation();
|
|
13461
14317
|
},
|
|
13462
|
-
children: /* @__PURE__ */ (0,
|
|
14318
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(import_lucide_react17.Link, { className: "size-4 shrink-0", "aria-hidden": true })
|
|
13463
14319
|
}
|
|
13464
14320
|
) : null
|
|
13465
14321
|
] })
|
|
@@ -13476,7 +14332,7 @@ function StateToggle({
|
|
|
13476
14332
|
states,
|
|
13477
14333
|
onStateChange
|
|
13478
14334
|
}) {
|
|
13479
|
-
return /* @__PURE__ */ (0,
|
|
14335
|
+
return /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
|
|
13480
14336
|
ToggleGroup,
|
|
13481
14337
|
{
|
|
13482
14338
|
"data-ohw-state-toggle": "",
|
|
@@ -13490,11 +14346,12 @@ function StateToggle({
|
|
|
13490
14346
|
left: rect.right - 8,
|
|
13491
14347
|
transform: "translateX(-100%)"
|
|
13492
14348
|
},
|
|
13493
|
-
children: states.map((state) => /* @__PURE__ */ (0,
|
|
14349
|
+
children: states.map((state) => /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(ToggleGroupItem, { value: state, size: "sm", children: state }, state))
|
|
13494
14350
|
}
|
|
13495
14351
|
);
|
|
13496
14352
|
}
|
|
13497
14353
|
var contentCache = /* @__PURE__ */ new Map();
|
|
14354
|
+
var fetchedContentPaths = /* @__PURE__ */ new Set();
|
|
13498
14355
|
function resolveSubdomain(subdomainFromQuery) {
|
|
13499
14356
|
if (subdomainFromQuery) return subdomainFromQuery;
|
|
13500
14357
|
if (typeof window !== "undefined") {
|
|
@@ -13589,8 +14446,14 @@ function OhhwellsBridge() {
|
|
|
13589
14446
|
});
|
|
13590
14447
|
const selectFrameRef = (0, import_react16.useRef)(() => {
|
|
13591
14448
|
});
|
|
14449
|
+
const selectLogoRef = (0, import_react16.useRef)(() => {
|
|
14450
|
+
});
|
|
14451
|
+
const openLogoSizePanelRef = (0, import_react16.useRef)(() => {
|
|
14452
|
+
});
|
|
13592
14453
|
const deselectRef = (0, import_react16.useRef)(() => {
|
|
13593
14454
|
});
|
|
14455
|
+
const closeFloatingPanelOnlyRef = (0, import_react16.useRef)(() => {
|
|
14456
|
+
});
|
|
13594
14457
|
const reselectNavigationItemRef = (0, import_react16.useRef)(() => {
|
|
13595
14458
|
});
|
|
13596
14459
|
const commitNavigationTextEditRef = (0, import_react16.useRef)(() => {
|
|
@@ -13623,17 +14486,34 @@ function OhhwellsBridge() {
|
|
|
13623
14486
|
const [hoveredNavContainerRect, setHoveredNavContainerRect] = (0, import_react16.useState)(null);
|
|
13624
14487
|
const hoveredItemElRef = (0, import_react16.useRef)(null);
|
|
13625
14488
|
const [hoveredItemRect, setHoveredItemRect] = (0, import_react16.useState)(null);
|
|
14489
|
+
const [hoveredTextRect, setHoveredTextRect] = (0, import_react16.useState)(null);
|
|
14490
|
+
(0, import_react16.useEffect)(() => {
|
|
14491
|
+
const sync = () => {
|
|
14492
|
+
const el = document.querySelector(
|
|
14493
|
+
"[data-ohw-hovered]:not([contenteditable]):not([data-ohw-href-key])"
|
|
14494
|
+
);
|
|
14495
|
+
const target = el && !el.closest("[data-ohw-href-key]") ? el : null;
|
|
14496
|
+
if (!target) {
|
|
14497
|
+
setHoveredTextRect(null);
|
|
14498
|
+
return;
|
|
14499
|
+
}
|
|
14500
|
+
const r2 = target.getBoundingClientRect();
|
|
14501
|
+
setHoveredTextRect(new DOMRect(r2.x - TEXT_HOVER_SIDE_PAD, r2.y, r2.width + TEXT_HOVER_SIDE_PAD * 2, r2.height));
|
|
14502
|
+
};
|
|
14503
|
+
const observer = new MutationObserver(sync);
|
|
14504
|
+
observer.observe(document.documentElement, {
|
|
14505
|
+
attributes: true,
|
|
14506
|
+
attributeFilter: ["data-ohw-hovered"],
|
|
14507
|
+
subtree: true
|
|
14508
|
+
});
|
|
14509
|
+
return () => observer.disconnect();
|
|
14510
|
+
}, []);
|
|
13626
14511
|
const siblingHintElRef = (0, import_react16.useRef)(null);
|
|
13627
14512
|
const [siblingHintRect, setSiblingHintRect] = (0, import_react16.useState)(null);
|
|
13628
14513
|
const [siblingHintRects, setSiblingHintRects] = (0, import_react16.useState)([]);
|
|
13629
14514
|
const [isItemDragging, setIsItemDragging] = (0, import_react16.useState)(false);
|
|
13630
14515
|
const [isFooterFrameSelection, setIsFooterFrameSelection] = (0, import_react16.useState)(false);
|
|
13631
14516
|
isFooterFrameSelectionRef.current = isFooterFrameSelection;
|
|
13632
|
-
const [floatingPanel, setFloatingPanel] = (0, import_react16.useState)(null);
|
|
13633
|
-
const floatingPanelOpenRef = (0, import_react16.useRef)(false);
|
|
13634
|
-
floatingPanelOpenRef.current = floatingPanel !== null;
|
|
13635
|
-
const [floatingPanelPos, setFloatingPanelPos] = (0, import_react16.useState)(null);
|
|
13636
|
-
const [parentScrollSnap, setParentScrollSnap] = (0, import_react16.useState)(null);
|
|
13637
14517
|
const [navDropdownPreviewOpen, setNavDropdownPreviewOpen] = (0, import_react16.useState)(null);
|
|
13638
14518
|
const [footerHeadingVisible, setFooterHeadingVisible] = (0, import_react16.useState)(null);
|
|
13639
14519
|
const footerDragRef = (0, import_react16.useRef)(null);
|
|
@@ -13648,7 +14528,16 @@ function OhhwellsBridge() {
|
|
|
13648
14528
|
const addNavAfterAnchorRef = (0, import_react16.useRef)(null);
|
|
13649
14529
|
const editContentRef = (0, import_react16.useRef)({});
|
|
13650
14530
|
const aiSectionsRef = (0, import_react16.useRef)("");
|
|
14531
|
+
const brandKitRef = (0, import_react16.useRef)("");
|
|
14532
|
+
const stylesRef = (0, import_react16.useRef)("");
|
|
13651
14533
|
const pendingDeleteUndoRef = (0, import_react16.useRef)(null);
|
|
14534
|
+
const [floatingPanel, setFloatingPanel] = (0, import_react16.useState)(null);
|
|
14535
|
+
const floatingPanelOpenRef = (0, import_react16.useRef)(false);
|
|
14536
|
+
const setFloatingPanelRef = (0, import_react16.useRef)(setFloatingPanel);
|
|
14537
|
+
const [floatingPanelPos, setFloatingPanelPos] = (0, import_react16.useState)(null);
|
|
14538
|
+
const [logoSizeDraft, setLogoSizeDraft] = (0, import_react16.useState)(null);
|
|
14539
|
+
const [editorViewport, setEditorViewport] = (0, import_react16.useState)("desktop");
|
|
14540
|
+
const [parentScrollSnap, setParentScrollSnap] = (0, import_react16.useState)(null);
|
|
13652
14541
|
const [sitePages, setSitePages] = (0, import_react16.useState)([]);
|
|
13653
14542
|
const [sectionsByPath, setSectionsByPath] = (0, import_react16.useState)({});
|
|
13654
14543
|
const sectionsPrefetchGenRef = (0, import_react16.useRef)(0);
|
|
@@ -13657,7 +14546,18 @@ function OhhwellsBridge() {
|
|
|
13657
14546
|
const linkPopoverOpenRef = (0, import_react16.useRef)(false);
|
|
13658
14547
|
const linkPopoverGraceUntilRef = (0, import_react16.useRef)(0);
|
|
13659
14548
|
setLinkPopoverRef.current = setLinkPopover;
|
|
14549
|
+
setFloatingPanelRef.current = setFloatingPanel;
|
|
13660
14550
|
linkPopoverSessionRef.current = linkPopover;
|
|
14551
|
+
floatingPanelOpenRef.current = Boolean(floatingPanel);
|
|
14552
|
+
(0, import_react16.useEffect)(() => {
|
|
14553
|
+
const syncViewport = () => {
|
|
14554
|
+
const next = window.innerWidth <= 480 ? "mobile" : "desktop";
|
|
14555
|
+
setEditorViewport((prev) => prev === next ? prev : next);
|
|
14556
|
+
};
|
|
14557
|
+
syncViewport();
|
|
14558
|
+
window.addEventListener("resize", syncViewport);
|
|
14559
|
+
return () => window.removeEventListener("resize", syncViewport);
|
|
14560
|
+
}, []);
|
|
13661
14561
|
const {
|
|
13662
14562
|
navDragRef,
|
|
13663
14563
|
navDropSlots,
|
|
@@ -13880,6 +14780,10 @@ function OhhwellsBridge() {
|
|
|
13880
14780
|
setIsItemDragging(false);
|
|
13881
14781
|
hoveredNavContainerRef.current = null;
|
|
13882
14782
|
setHoveredNavContainerRect(null);
|
|
14783
|
+
hoveredItemElRef.current = null;
|
|
14784
|
+
setHoveredItemRect(null);
|
|
14785
|
+
setFloatingPanel(null);
|
|
14786
|
+
setLogoSizeDraft(null);
|
|
13883
14787
|
if (!activeElRef.current) {
|
|
13884
14788
|
setNavGroupForceOpen(null, false);
|
|
13885
14789
|
setToolbarRect(null);
|
|
@@ -14076,6 +14980,14 @@ function OhhwellsBridge() {
|
|
|
14076
14980
|
if (!selected) return;
|
|
14077
14981
|
const socialsRow = isSocialsRow(selected) ? selected : findSocialsRow(selected);
|
|
14078
14982
|
if (socialsRow) {
|
|
14983
|
+
if (!canAddSocialItem(socialsRow)) {
|
|
14984
|
+
postToParent2({
|
|
14985
|
+
type: "ow:toast",
|
|
14986
|
+
title: `Maximum ${MAX_SOCIAL_ITEMS_PER_ROW} social icons`,
|
|
14987
|
+
toastType: "error"
|
|
14988
|
+
});
|
|
14989
|
+
return;
|
|
14990
|
+
}
|
|
14079
14991
|
const after = getSocialItem(selected);
|
|
14080
14992
|
const result2 = insertSocialItem(socialsRow, after, editContentRef.current);
|
|
14081
14993
|
if (!result2) return;
|
|
@@ -14097,10 +15009,16 @@ function OhhwellsBridge() {
|
|
|
14097
15009
|
return;
|
|
14098
15010
|
}
|
|
14099
15011
|
if (toolbarVariantRef.current === "select-frame" && isFooterFrameSelection) {
|
|
14100
|
-
|
|
14101
|
-
}
|
|
14102
|
-
const column = (selected.hasAttribute("data-ohw-footer-col") ? selected : null) ?? selected.closest("[data-ohw-footer-col]") ?? (listFooterColumns().includes(selected) ? selected : null);
|
|
15012
|
+
const column = resolveFooterColumnForAdd(selected);
|
|
14103
15013
|
if (!column) return;
|
|
15014
|
+
if (!canAddFooterItem(column)) {
|
|
15015
|
+
postToParent2({
|
|
15016
|
+
type: "ow:toast",
|
|
15017
|
+
title: `Maximum ${MAX_FOOTER_ITEMS_PER_COLUMN} items per column`,
|
|
15018
|
+
toastType: "error"
|
|
15019
|
+
});
|
|
15020
|
+
return;
|
|
15021
|
+
}
|
|
14104
15022
|
const result2 = insertFooterItem(column, "/", "New link", null);
|
|
14105
15023
|
applyLinkByKey(result2.hrefKey, result2.href);
|
|
14106
15024
|
document.querySelectorAll(`[data-ohw-key="${result2.labelKey}"]`).forEach((el) => {
|
|
@@ -14571,6 +15489,8 @@ function OhhwellsBridge() {
|
|
|
14571
15489
|
setToolbarRect(anchor.getBoundingClientRect());
|
|
14572
15490
|
setToolbarShowEditLink(false);
|
|
14573
15491
|
setActiveCommands(/* @__PURE__ */ new Set());
|
|
15492
|
+
setFloatingPanel(null);
|
|
15493
|
+
setLogoSizeDraft(null);
|
|
14574
15494
|
}, [deactivate, markSelected]);
|
|
14575
15495
|
const selectFrame = (0, import_react16.useCallback)((el) => {
|
|
14576
15496
|
if (!isNavigationContainer(el)) return;
|
|
@@ -14620,7 +15540,51 @@ function OhhwellsBridge() {
|
|
|
14620
15540
|
setToolbarRect(el.getBoundingClientRect());
|
|
14621
15541
|
setToolbarShowEditLink(false);
|
|
14622
15542
|
setActiveCommands(/* @__PURE__ */ new Set());
|
|
15543
|
+
setFloatingPanel(null);
|
|
15544
|
+
setLogoSizeDraft(null);
|
|
14623
15545
|
}, [deactivate, markSelected, postToParent2]);
|
|
15546
|
+
const selectLogo = (0, import_react16.useCallback)(
|
|
15547
|
+
(logoEl) => {
|
|
15548
|
+
if (activeElRef.current) deactivate();
|
|
15549
|
+
selectedElRef.current = logoEl;
|
|
15550
|
+
selectedHrefKeyRef.current = null;
|
|
15551
|
+
selectedFooterColAttrRef.current = null;
|
|
15552
|
+
markSelected(logoEl);
|
|
15553
|
+
setSelectedIsCta(false);
|
|
15554
|
+
setSelectedIsSocial(false);
|
|
15555
|
+
setSelectedIsSocialsRow(false);
|
|
15556
|
+
clearHrefKeyHover(logoEl);
|
|
15557
|
+
hoveredNavContainerRef.current = null;
|
|
15558
|
+
setHoveredNavContainerRect(null);
|
|
15559
|
+
setHoveredItemRect(null);
|
|
15560
|
+
hoveredItemElRef.current = null;
|
|
15561
|
+
siblingHintElRef.current = null;
|
|
15562
|
+
setSiblingHintRect(null);
|
|
15563
|
+
setSiblingHintRects([]);
|
|
15564
|
+
setIsItemDragging(false);
|
|
15565
|
+
setReorderHrefKey(null);
|
|
15566
|
+
setReorderDragDisabled(false);
|
|
15567
|
+
setIsFooterFrameSelection(false);
|
|
15568
|
+
setToolbarVariant("logo");
|
|
15569
|
+
setToolbarRect(getLogoInteractionRect(logoEl));
|
|
15570
|
+
setToolbarShowEditLink(false);
|
|
15571
|
+
setActiveCommands(/* @__PURE__ */ new Set());
|
|
15572
|
+
},
|
|
15573
|
+
[deactivate, markSelected]
|
|
15574
|
+
);
|
|
15575
|
+
const openLogoSizePanel = (0, import_react16.useCallback)((logoEl) => {
|
|
15576
|
+
const placement = getLogoPlacement(logoEl);
|
|
15577
|
+
const draft = readLogoSizeState(editContentRef.current, placement);
|
|
15578
|
+
setLogoSizeDraft(draft);
|
|
15579
|
+
setParentScrollSnap(parentScrollRef.current);
|
|
15580
|
+
setFloatingPanel({
|
|
15581
|
+
key: `logo-size:${placement}`,
|
|
15582
|
+
title: "Logo",
|
|
15583
|
+
context: placement === "navbar" ? "Navbar" : "Footer",
|
|
15584
|
+
kind: "logo-size",
|
|
15585
|
+
placement
|
|
15586
|
+
});
|
|
15587
|
+
}, []);
|
|
14624
15588
|
const openSocialsDisplayPanel = (0, import_react16.useCallback)((row) => {
|
|
14625
15589
|
setParentScrollSnap(parentScrollRef.current);
|
|
14626
15590
|
setFloatingPanel({
|
|
@@ -14656,13 +15620,53 @@ function OhhwellsBridge() {
|
|
|
14656
15620
|
);
|
|
14657
15621
|
const closeFloatingPanelOnly = (0, import_react16.useCallback)(() => {
|
|
14658
15622
|
setFloatingPanel(null);
|
|
15623
|
+
setLogoSizeDraft(null);
|
|
14659
15624
|
}, []);
|
|
14660
|
-
const closeFloatingPanelOnlyRef = (0, import_react16.useRef)(closeFloatingPanelOnly);
|
|
14661
|
-
closeFloatingPanelOnlyRef.current = closeFloatingPanelOnly;
|
|
14662
15625
|
const closeFloatingPanelAndDeselect = (0, import_react16.useCallback)(() => {
|
|
14663
15626
|
setFloatingPanel(null);
|
|
15627
|
+
setLogoSizeDraft(null);
|
|
14664
15628
|
deselectRef.current();
|
|
14665
15629
|
}, []);
|
|
15630
|
+
const persistLogoSizeDraft = (0, import_react16.useCallback)(
|
|
15631
|
+
(placement, draft) => {
|
|
15632
|
+
const desktopKey = LOGO_SIZE_DESKTOP_KEYS[placement];
|
|
15633
|
+
const mobileKey = LOGO_SIZE_MOBILE_KEYS[placement];
|
|
15634
|
+
const nodes = [
|
|
15635
|
+
{ key: desktopKey, text: String(draft.desktopPx) }
|
|
15636
|
+
];
|
|
15637
|
+
if (draft.mobileFollowing) {
|
|
15638
|
+
nodes.push({ key: mobileKey, text: "" });
|
|
15639
|
+
} else {
|
|
15640
|
+
nodes.push({ key: mobileKey, text: String(draft.mobilePx) });
|
|
15641
|
+
}
|
|
15642
|
+
editContentRef.current = {
|
|
15643
|
+
...editContentRef.current,
|
|
15644
|
+
[desktopKey]: String(draft.desktopPx),
|
|
15645
|
+
[mobileKey]: draft.mobileFollowing ? "" : String(draft.mobilePx)
|
|
15646
|
+
};
|
|
15647
|
+
applyLogoSizeToPlacement(
|
|
15648
|
+
placement,
|
|
15649
|
+
draft.desktopPx,
|
|
15650
|
+
draft.mobileFollowing ? draft.desktopPx : draft.mobilePx,
|
|
15651
|
+
draft.mobileFollowing
|
|
15652
|
+
);
|
|
15653
|
+
postToParent2({ type: "ow:change", nodes });
|
|
15654
|
+
requestAnimationFrame(() => {
|
|
15655
|
+
const selected = selectedElRef.current;
|
|
15656
|
+
if (!selected || toolbarVariantRef.current !== "logo") return;
|
|
15657
|
+
const rect = getLogoInteractionRect(selected);
|
|
15658
|
+
setToolbarRect(rect);
|
|
15659
|
+
if (glowElRef.current) {
|
|
15660
|
+
const GAP = SELECTION_CHROME_GAP2;
|
|
15661
|
+
glowElRef.current.style.top = `${rect.top - GAP}px`;
|
|
15662
|
+
glowElRef.current.style.left = `${rect.left - GAP}px`;
|
|
15663
|
+
glowElRef.current.style.width = `${rect.width + GAP * 2}px`;
|
|
15664
|
+
glowElRef.current.style.height = `${rect.height + GAP * 2}px`;
|
|
15665
|
+
}
|
|
15666
|
+
});
|
|
15667
|
+
},
|
|
15668
|
+
[postToParent2]
|
|
15669
|
+
);
|
|
14666
15670
|
const activate = (0, import_react16.useCallback)((el, options) => {
|
|
14667
15671
|
if (activeElRef.current === el) return;
|
|
14668
15672
|
if (isIconEditable(el)) return;
|
|
@@ -14743,7 +15747,37 @@ function OhhwellsBridge() {
|
|
|
14743
15747
|
deactivateRef.current = deactivate;
|
|
14744
15748
|
selectRef.current = select;
|
|
14745
15749
|
selectFrameRef.current = selectFrame;
|
|
15750
|
+
selectLogoRef.current = selectLogo;
|
|
15751
|
+
openLogoSizePanelRef.current = openLogoSizePanel;
|
|
14746
15752
|
deselectRef.current = deselect;
|
|
15753
|
+
closeFloatingPanelOnlyRef.current = closeFloatingPanelOnly;
|
|
15754
|
+
const lastSiteWideScopeRef = (0, import_react16.useRef)(null);
|
|
15755
|
+
(0, import_react16.useEffect)(() => {
|
|
15756
|
+
if (!isEditMode) {
|
|
15757
|
+
if (lastSiteWideScopeRef.current !== false) {
|
|
15758
|
+
lastSiteWideScopeRef.current = false;
|
|
15759
|
+
postToParent2({ type: "ow:site-wide-scope", active: false });
|
|
15760
|
+
}
|
|
15761
|
+
return;
|
|
15762
|
+
}
|
|
15763
|
+
const active = isSiteWideScopeActive({
|
|
15764
|
+
selected: selectedElRef.current,
|
|
15765
|
+
hoveredItem: hoveredItemElRef.current,
|
|
15766
|
+
hoveredNavContainer: hoveredNavContainerRef.current,
|
|
15767
|
+
active: activeElRef.current
|
|
15768
|
+
});
|
|
15769
|
+
if (lastSiteWideScopeRef.current === active) return;
|
|
15770
|
+
lastSiteWideScopeRef.current = active;
|
|
15771
|
+
postToParent2({ type: "ow:site-wide-scope", active });
|
|
15772
|
+
}, [
|
|
15773
|
+
isEditMode,
|
|
15774
|
+
hoveredItemRect,
|
|
15775
|
+
hoveredNavContainerRect,
|
|
15776
|
+
toolbarVariant,
|
|
15777
|
+
toolbarRect,
|
|
15778
|
+
isFooterFrameSelection,
|
|
15779
|
+
postToParent2
|
|
15780
|
+
]);
|
|
14747
15781
|
(0, import_react16.useLayoutEffect)(() => {
|
|
14748
15782
|
if (!subdomain || isEditMode) {
|
|
14749
15783
|
setFetchState("done");
|
|
@@ -14755,9 +15789,23 @@ function OhhwellsBridge() {
|
|
|
14755
15789
|
aiSectionsRef.current = content[AI_SECTIONS_KEY];
|
|
14756
15790
|
applyAiSectionsToDom(parseAiSectionsState(content[AI_SECTIONS_KEY]));
|
|
14757
15791
|
}
|
|
15792
|
+
if (typeof content[BRAND_KIT_KEY] === "string") {
|
|
15793
|
+
brandKitRef.current = content[BRAND_KIT_KEY];
|
|
15794
|
+
applyBrandToDom(parseBrandKit(content[BRAND_KIT_KEY]));
|
|
15795
|
+
}
|
|
15796
|
+
if (typeof content[STYLE_STORE_KEY] === "string") {
|
|
15797
|
+
stylesRef.current = content[STYLE_STORE_KEY];
|
|
15798
|
+
applyStylesToDom(parseStyleStore(content[STYLE_STORE_KEY]));
|
|
15799
|
+
}
|
|
15800
|
+
applyBrandChrome(content);
|
|
14758
15801
|
for (const [key, val] of Object.entries(content)) {
|
|
14759
15802
|
if (key === "__ohw_sections") continue;
|
|
14760
15803
|
if (key === AI_SECTIONS_KEY) continue;
|
|
15804
|
+
if (key === LOGO_PLACEHOLDER_KEY) continue;
|
|
15805
|
+
if (LOGO_IMAGE_KEYS.includes(key)) continue;
|
|
15806
|
+
if (key === BRAND_KIT_KEY) continue;
|
|
15807
|
+
if (key === STYLE_STORE_KEY) continue;
|
|
15808
|
+
if (BRAND_CHROME_KEYS.has(key)) continue;
|
|
14761
15809
|
if (applyVideoSettingNode(key, val)) continue;
|
|
14762
15810
|
if (applyCarouselNode(key, val)) continue;
|
|
14763
15811
|
document.querySelectorAll(`[data-ohw-key="${key}"]`).forEach((el) => {
|
|
@@ -14792,6 +15840,8 @@ function OhhwellsBridge() {
|
|
|
14792
15840
|
});
|
|
14793
15841
|
applyLinkByKey(key, val);
|
|
14794
15842
|
}
|
|
15843
|
+
applyLogoFromContent(content);
|
|
15844
|
+
applyLogoSizes(content);
|
|
14795
15845
|
reconcileNavbarItemsFromContent(content);
|
|
14796
15846
|
reconcileFooterOrderFromContent(content);
|
|
14797
15847
|
reconcileSocialsFromContent(content);
|
|
@@ -14812,7 +15862,9 @@ function OhhwellsBridge() {
|
|
|
14812
15862
|
let cancelled = false;
|
|
14813
15863
|
setFetchState("loading");
|
|
14814
15864
|
const apiUrl = process.env.NEXT_PUBLIC_FLOWOPS_API_URL ?? "https://flowops-backend-staging-2yfdh7pwpq-as.a.run.app";
|
|
14815
|
-
|
|
15865
|
+
const initialPath = pathname;
|
|
15866
|
+
fetchedContentPaths.add(`${subdomain}::${initialPath}`);
|
|
15867
|
+
fetch(`${apiUrl}/api/public/sites/${subdomain}/content?path=${encodeURIComponent(initialPath)}`, { cache: "no-store" }).then((r2) => r2.ok ? r2.json() : null).then((data) => {
|
|
14816
15868
|
if (cancelled) return;
|
|
14817
15869
|
const content = data?.content ?? {};
|
|
14818
15870
|
contentCache.set(subdomain, content);
|
|
@@ -14836,8 +15888,21 @@ function OhhwellsBridge() {
|
|
|
14836
15888
|
initSectionInstancesFromContent(content, window.location.pathname);
|
|
14837
15889
|
observer?.disconnect();
|
|
14838
15890
|
try {
|
|
15891
|
+
applyBrandChrome(content);
|
|
15892
|
+
if (typeof content[BRAND_KIT_KEY] === "string") {
|
|
15893
|
+
applyBrandToDom(parseBrandKit(content[BRAND_KIT_KEY]));
|
|
15894
|
+
}
|
|
15895
|
+
if (typeof content[STYLE_STORE_KEY] === "string") {
|
|
15896
|
+
applyStylesToDom(parseStyleStore(content[STYLE_STORE_KEY]));
|
|
15897
|
+
}
|
|
14839
15898
|
for (const [key, val] of Object.entries(content)) {
|
|
14840
15899
|
if (key === "__ohw_sections") continue;
|
|
15900
|
+
if (key === LOGO_PLACEHOLDER_KEY) continue;
|
|
15901
|
+
if (LOGO_IMAGE_KEYS.includes(key)) continue;
|
|
15902
|
+
if (key === BRAND_KIT_KEY) continue;
|
|
15903
|
+
if (key === STYLE_STORE_KEY) continue;
|
|
15904
|
+
if (key === STYLE_STORE_KEY) continue;
|
|
15905
|
+
if (BRAND_CHROME_KEYS.has(key)) continue;
|
|
14841
15906
|
if (applyVideoSettingNode(key, val)) continue;
|
|
14842
15907
|
if (applyCarouselNode(key, val)) continue;
|
|
14843
15908
|
document.querySelectorAll(`[data-ohw-key="${key}"]`).forEach((el) => {
|
|
@@ -14858,6 +15923,7 @@ function OhhwellsBridge() {
|
|
|
14858
15923
|
});
|
|
14859
15924
|
applyLinkByKey(key, val);
|
|
14860
15925
|
}
|
|
15926
|
+
applyLogoFromContent(content);
|
|
14861
15927
|
reconcileNavbarItemsFromContent(content);
|
|
14862
15928
|
reconcileFooterOrderFromContent(content);
|
|
14863
15929
|
reconcileSocialsFromContent(content);
|
|
@@ -14872,6 +15938,17 @@ function OhhwellsBridge() {
|
|
|
14872
15938
|
debounceTimer = setTimeout(applyFromCache, 150);
|
|
14873
15939
|
};
|
|
14874
15940
|
applyFromCache();
|
|
15941
|
+
const pathCacheKey = `${subdomain}::${pathname}`;
|
|
15942
|
+
if (!fetchedContentPaths.has(pathCacheKey)) {
|
|
15943
|
+
fetchedContentPaths.add(pathCacheKey);
|
|
15944
|
+
const apiUrl = process.env.NEXT_PUBLIC_FLOWOPS_API_URL ?? "https://flowops-backend-staging-2yfdh7pwpq-as.a.run.app";
|
|
15945
|
+
fetch(`${apiUrl}/api/public/sites/${subdomain}/content?path=${encodeURIComponent(pathname)}`, { cache: "no-store" }).then((r2) => r2.ok ? r2.json() : null).then((data) => {
|
|
15946
|
+
if (!data?.content) return;
|
|
15947
|
+
contentCache.set(subdomain, data.content);
|
|
15948
|
+
applyFromCache();
|
|
15949
|
+
}).catch(() => {
|
|
15950
|
+
});
|
|
15951
|
+
}
|
|
14875
15952
|
observer = new MutationObserver(scheduleApply);
|
|
14876
15953
|
observer.observe(document.body, { childList: true, subtree: true });
|
|
14877
15954
|
return () => {
|
|
@@ -14965,26 +16042,31 @@ function OhhwellsBridge() {
|
|
|
14965
16042
|
}, [isEditMode, pathname, subdomain, fetchState, resyncSelectedNavigationItem]);
|
|
14966
16043
|
(0, import_react16.useEffect)(() => {
|
|
14967
16044
|
if (!isEditMode) return;
|
|
16045
|
+
let lastPosted = 0;
|
|
14968
16046
|
const measure = () => {
|
|
14969
16047
|
const h = document.body.scrollHeight;
|
|
14970
|
-
if (h > 50
|
|
16048
|
+
if (h > 50 && Math.abs(h - lastPosted) > 1) {
|
|
16049
|
+
lastPosted = h;
|
|
16050
|
+
postToParent2({ type: "ow:height", height: h });
|
|
16051
|
+
}
|
|
16052
|
+
};
|
|
16053
|
+
let raf = null;
|
|
16054
|
+
const schedule = () => {
|
|
16055
|
+
if (raf != null) return;
|
|
16056
|
+
raf = requestAnimationFrame(() => {
|
|
16057
|
+
raf = null;
|
|
16058
|
+
measure();
|
|
16059
|
+
});
|
|
14971
16060
|
};
|
|
14972
16061
|
const t1 = setTimeout(measure, 50);
|
|
14973
16062
|
const t2 = setTimeout(measure, 500);
|
|
14974
|
-
|
|
14975
|
-
|
|
14976
|
-
const handleResize = () => {
|
|
14977
|
-
if (window.innerWidth === lastWidth) return;
|
|
14978
|
-
lastWidth = window.innerWidth;
|
|
14979
|
-
if (resizeTimer) clearTimeout(resizeTimer);
|
|
14980
|
-
resizeTimer = setTimeout(measure, 150);
|
|
14981
|
-
};
|
|
14982
|
-
window.addEventListener("resize", handleResize);
|
|
16063
|
+
const ro = new ResizeObserver(schedule);
|
|
16064
|
+
ro.observe(document.body);
|
|
14983
16065
|
return () => {
|
|
14984
16066
|
clearTimeout(t1);
|
|
14985
16067
|
clearTimeout(t2);
|
|
14986
|
-
if (
|
|
14987
|
-
|
|
16068
|
+
if (raf != null) cancelAnimationFrame(raf);
|
|
16069
|
+
ro.disconnect();
|
|
14988
16070
|
};
|
|
14989
16071
|
}, [pathname, isEditMode, postToParent2]);
|
|
14990
16072
|
(0, import_react16.useEffect)(() => {
|
|
@@ -15054,9 +16136,12 @@ function OhhwellsBridge() {
|
|
|
15054
16136
|
[data-ohw-editable="video"], [data-ohw-editable="video"] *,
|
|
15055
16137
|
[data-ohw-editable="bg-image"], [data-ohw-editable="bg-image"] * { cursor: pointer !important; }
|
|
15056
16138
|
[data-ohw-editable="link"], [data-ohw-editable="link"] * { cursor: pointer !important; }
|
|
16139
|
+
/* Text hover chrome is drawn by the overlay (see hoveredTextRect) \u2014 the CSS outline
|
|
16140
|
+
that used to draw it dashes denser than the overlay border, so identical specs
|
|
16141
|
+
still read as two different frames (OHH-695). The attribute stays: hover paths
|
|
16142
|
+
and suppression rules key off it. */
|
|
15057
16143
|
[data-ohw-hovered]:not([contenteditable]):not([data-ohw-href-key]) {
|
|
15058
|
-
outline:
|
|
15059
|
-
outline-offset: 4px;
|
|
16144
|
+
outline: none !important;
|
|
15060
16145
|
}
|
|
15061
16146
|
[data-ohw-href-key] [data-ohw-hovered],
|
|
15062
16147
|
[data-ohw-href-key][data-ohw-hovered],
|
|
@@ -15109,8 +16194,11 @@ function OhhwellsBridge() {
|
|
|
15109
16194
|
stateViews.textContent = `
|
|
15110
16195
|
[data-ohw-state-view]:not([data-ohw-state-view="default"]) { display: none; }
|
|
15111
16196
|
[data-ohw-state-view="default"] [data-ohw-editable] { pointer-events: auto !important; }
|
|
15112
|
-
[data-ohw-state-hovered] { outline:
|
|
16197
|
+
[data-ohw-state-hovered] { outline: ${HOVER_STROKE_WIDTH}px dashed ${CHROME_PRIMARY} !important; outline-offset: ${HOVER_CHROME_GAP}px; }
|
|
15113
16198
|
[data-ohw-state-hovered]:has([data-ohw-hovered]) { outline: none !important; }
|
|
16199
|
+
/* :has() only sees descendants \u2014 when the card itself is the hovered text, the overlay
|
|
16200
|
+
already frames it, and the card outline doubled it (OHH-695). */
|
|
16201
|
+
[data-ohw-state-hovered][data-ohw-hovered] { outline: none !important; }
|
|
15114
16202
|
`;
|
|
15115
16203
|
document.head.appendChild(base);
|
|
15116
16204
|
document.head.appendChild(forceHover);
|
|
@@ -15128,10 +16216,12 @@ function OhhwellsBridge() {
|
|
|
15128
16216
|
return;
|
|
15129
16217
|
}
|
|
15130
16218
|
const target = e.target;
|
|
16219
|
+
if (target.closest("[data-ohw-ai-review]")) return;
|
|
15131
16220
|
if (target.closest("[data-ohw-toolbar]")) return;
|
|
15132
16221
|
if (target.closest("[data-ohw-state-toggle]")) return;
|
|
15133
16222
|
if (target.closest("[data-ohw-max-badge]")) return;
|
|
15134
16223
|
if (isInsideLinkEditor(target)) return;
|
|
16224
|
+
if (isInsideFloatingPanel(target)) return;
|
|
15135
16225
|
if (target.closest('[data-ohw-edit-chrome], [data-ohw-item-interaction], [data-ohw-drag-handle-container], [data-slot="drag-handle"]')) {
|
|
15136
16226
|
const beneath = document.elementsFromPoint(e.clientX, e.clientY).find(
|
|
15137
16227
|
(el) => el instanceof HTMLElement && !el.closest("[data-ohw-bridge-root]") && el.closest("[data-ohw-section]") != null
|
|
@@ -15195,6 +16285,21 @@ function OhhwellsBridge() {
|
|
|
15195
16285
|
return;
|
|
15196
16286
|
}
|
|
15197
16287
|
}
|
|
16288
|
+
const logoEl = getLogoElement(target);
|
|
16289
|
+
if (logoEl) {
|
|
16290
|
+
e.preventDefault();
|
|
16291
|
+
e.stopPropagation();
|
|
16292
|
+
if (!logoHasUploadedImage(logoEl)) {
|
|
16293
|
+
deselectRef.current();
|
|
16294
|
+
deactivateRef.current();
|
|
16295
|
+
const identity = readLogoIdentityFromDom();
|
|
16296
|
+
postToParentRef.current({ type: "ow:open-logo-settings", ...identity });
|
|
16297
|
+
return;
|
|
16298
|
+
}
|
|
16299
|
+
selectLogoRef.current(logoEl);
|
|
16300
|
+
openLogoSizePanelRef.current(logoEl);
|
|
16301
|
+
return;
|
|
16302
|
+
}
|
|
15198
16303
|
const editable = target.closest("[data-ohw-editable]");
|
|
15199
16304
|
if (editable) {
|
|
15200
16305
|
if (editable.dataset.ohwEditable === "link") {
|
|
@@ -15347,10 +16452,12 @@ function OhhwellsBridge() {
|
|
|
15347
16452
|
};
|
|
15348
16453
|
const handleDblClick = (e) => {
|
|
15349
16454
|
const target = e.target;
|
|
16455
|
+
if (target.closest("[data-ohw-ai-review]")) return;
|
|
15350
16456
|
if (target.closest("[data-ohw-toolbar]")) return;
|
|
15351
16457
|
if (target.closest("[data-ohw-state-toggle]")) return;
|
|
15352
16458
|
if (target.closest("[data-ohw-max-badge]")) return;
|
|
15353
16459
|
if (isInsideLinkEditor(target)) return;
|
|
16460
|
+
if (isInsideFloatingPanel(target)) return;
|
|
15354
16461
|
if (target.closest('[data-ohw-edit-chrome], [data-ohw-item-interaction], [data-ohw-drag-handle-container], [data-slot="drag-handle"]')) {
|
|
15355
16462
|
return;
|
|
15356
16463
|
}
|
|
@@ -15378,6 +16485,16 @@ function OhhwellsBridge() {
|
|
|
15378
16485
|
setHoveredNavContainerRect(null);
|
|
15379
16486
|
return;
|
|
15380
16487
|
}
|
|
16488
|
+
if (document.documentElement.hasAttribute("data-ohw-panel-dragging") || isInsideFloatingPanel(target) || isPointOverFloatingPanel(e.clientX, e.clientY)) {
|
|
16489
|
+
hoveredItemElRef.current = null;
|
|
16490
|
+
setHoveredItemRect(null);
|
|
16491
|
+
hoveredNavContainerRef.current = null;
|
|
16492
|
+
setHoveredNavContainerRect(null);
|
|
16493
|
+
siblingHintElRef.current = null;
|
|
16494
|
+
setSiblingHintRect(null);
|
|
16495
|
+
setSiblingHintRects([]);
|
|
16496
|
+
return;
|
|
16497
|
+
}
|
|
15381
16498
|
{
|
|
15382
16499
|
const selected2 = selectedElRef.current;
|
|
15383
16500
|
const selectedIsFooterColumn = Boolean(selected2) && !isFooterLinksContainer(selected2) && (selected2.hasAttribute("data-ohw-footer-col") || selected2.hasAttribute("data-ohw-footer-column") || Boolean(selected2.closest("footer") && isInferredFooterGroup2(selected2)));
|
|
@@ -15385,7 +16502,7 @@ function OhhwellsBridge() {
|
|
|
15385
16502
|
const allowFooterLinksHover = toolbarVariantRef.current !== "select-frame" || selectedIsFooterColumn;
|
|
15386
16503
|
if (allowNavContainerHover) {
|
|
15387
16504
|
const navContainer = target.closest("[data-ohw-nav-container]");
|
|
15388
|
-
if (navContainer && !getNavigationItemAnchor(target)) {
|
|
16505
|
+
if (navContainer && !getNavigationItemAnchor(target) && !getLogoElement(target)) {
|
|
15389
16506
|
hoveredNavContainerRef.current = navContainer;
|
|
15390
16507
|
setHoveredNavContainerRect(navContainer.getBoundingClientRect());
|
|
15391
16508
|
hoveredItemElRef.current = null;
|
|
@@ -15414,6 +16531,15 @@ function OhhwellsBridge() {
|
|
|
15414
16531
|
setHoveredNavContainerRect(null);
|
|
15415
16532
|
}
|
|
15416
16533
|
}
|
|
16534
|
+
const logoEl = getLogoElement(target);
|
|
16535
|
+
if (logoEl) {
|
|
16536
|
+
hoveredNavContainerRef.current = null;
|
|
16537
|
+
setHoveredNavContainerRect(null);
|
|
16538
|
+
if (selectedElRef.current === logoEl) return;
|
|
16539
|
+
hoveredItemElRef.current = logoEl;
|
|
16540
|
+
setHoveredItemRect(getLogoInteractionRect(logoEl));
|
|
16541
|
+
return;
|
|
16542
|
+
}
|
|
15417
16543
|
const navAnchor = getNavigationItemAnchor(target);
|
|
15418
16544
|
if (navAnchor) {
|
|
15419
16545
|
hoveredNavContainerRef.current = null;
|
|
@@ -15451,6 +16577,11 @@ function OhhwellsBridge() {
|
|
|
15451
16577
|
setHoveredItemRect(hoverTarget.getBoundingClientRect());
|
|
15452
16578
|
} else if (!isInsideNavigationItem(editable)) {
|
|
15453
16579
|
hoverTarget.setAttribute("data-ohw-hovered", "");
|
|
16580
|
+
if (editable.closest("footer") || editable.closest('[data-ohw-section="footer"]')) {
|
|
16581
|
+
hoveredNavContainerRef.current = null;
|
|
16582
|
+
setHoveredNavContainerRect(null);
|
|
16583
|
+
hoveredItemElRef.current = editable;
|
|
16584
|
+
}
|
|
15454
16585
|
}
|
|
15455
16586
|
}
|
|
15456
16587
|
};
|
|
@@ -15486,6 +16617,18 @@ function OhhwellsBridge() {
|
|
|
15486
16617
|
}
|
|
15487
16618
|
return;
|
|
15488
16619
|
}
|
|
16620
|
+
const logoEl = getLogoElement(target);
|
|
16621
|
+
if (logoEl) {
|
|
16622
|
+
const related2 = e.relatedTarget instanceof Element ? e.relatedTarget : null;
|
|
16623
|
+
if (related2 && (logoEl === related2 || logoEl.contains(related2) || related2.closest?.('[data-ohw-role="logo"], [data-ohw-logo]'))) {
|
|
16624
|
+
return;
|
|
16625
|
+
}
|
|
16626
|
+
if (hoveredItemElRef.current === logoEl) {
|
|
16627
|
+
hoveredItemElRef.current = null;
|
|
16628
|
+
setHoveredItemRect(null);
|
|
16629
|
+
}
|
|
16630
|
+
return;
|
|
16631
|
+
}
|
|
15489
16632
|
const editable = target.closest("[data-ohw-editable]");
|
|
15490
16633
|
if (!editable) return;
|
|
15491
16634
|
const related = e.relatedTarget instanceof Element ? e.relatedTarget : null;
|
|
@@ -15506,6 +16649,13 @@ function OhhwellsBridge() {
|
|
|
15506
16649
|
}
|
|
15507
16650
|
} else {
|
|
15508
16651
|
hoverTarget.removeAttribute("data-ohw-hovered");
|
|
16652
|
+
if (hoveredItemElRef.current === editable) {
|
|
16653
|
+
const stillOnEditable = related instanceof Element && related.closest("[data-ohw-editable]") === editable;
|
|
16654
|
+
if (!stillOnEditable) {
|
|
16655
|
+
hoveredItemElRef.current = null;
|
|
16656
|
+
setHoveredItemRect(null);
|
|
16657
|
+
}
|
|
16658
|
+
}
|
|
15509
16659
|
}
|
|
15510
16660
|
}
|
|
15511
16661
|
};
|
|
@@ -15622,6 +16772,26 @@ function OhhwellsBridge() {
|
|
|
15622
16772
|
hoveredNavContainerRef.current = null;
|
|
15623
16773
|
setHoveredNavContainerRect(null);
|
|
15624
16774
|
}
|
|
16775
|
+
const logoCandidates = [
|
|
16776
|
+
...document.querySelectorAll('[data-ohw-role="logo"], [data-ohw-logo]'),
|
|
16777
|
+
...document.querySelectorAll("nav a:not([data-ohw-href-key]), [data-ohw-nav-root] a:not([data-ohw-href-key])"),
|
|
16778
|
+
...document.querySelectorAll("footer img")
|
|
16779
|
+
];
|
|
16780
|
+
const seenLogos = /* @__PURE__ */ new Set();
|
|
16781
|
+
for (const candidate of logoCandidates) {
|
|
16782
|
+
const logo = getLogoElement(candidate);
|
|
16783
|
+
if (!logo || seenLogos.has(logo)) continue;
|
|
16784
|
+
seenLogos.add(logo);
|
|
16785
|
+
const r2 = logo.getBoundingClientRect();
|
|
16786
|
+
if (x < r2.left || x > r2.right || y < r2.top || y > r2.bottom) continue;
|
|
16787
|
+
hoveredNavContainerRef.current = null;
|
|
16788
|
+
setHoveredNavContainerRect(null);
|
|
16789
|
+
if (selectedElRef.current !== logo) {
|
|
16790
|
+
hoveredItemElRef.current = logo;
|
|
16791
|
+
setHoveredItemRect(getLogoInteractionRect(logo));
|
|
16792
|
+
}
|
|
16793
|
+
return;
|
|
16794
|
+
}
|
|
15625
16795
|
const navContainers = Array.from(
|
|
15626
16796
|
document.querySelectorAll("[data-ohw-nav-container]")
|
|
15627
16797
|
);
|
|
@@ -15707,7 +16877,7 @@ function OhhwellsBridge() {
|
|
|
15707
16877
|
}
|
|
15708
16878
|
};
|
|
15709
16879
|
const probeImageAt = (clientX, clientY, isDragOver = false, fromParentViewport = false) => {
|
|
15710
|
-
if (linkPopoverOpenRef.current) {
|
|
16880
|
+
if (linkPopoverOpenRef.current || floatingPanelOpenRef.current && isPointOverFloatingPanel(clientX, clientY)) {
|
|
15711
16881
|
if (hoveredImageRef.current) {
|
|
15712
16882
|
hoveredImageRef.current = null;
|
|
15713
16883
|
hoveredImageHasTextOverlapRef.current = false;
|
|
@@ -15961,7 +17131,7 @@ function OhhwellsBridge() {
|
|
|
15961
17131
|
}
|
|
15962
17132
|
};
|
|
15963
17133
|
const probeHoverCardsAt = (clientX, clientY, fromParentViewport = false) => {
|
|
15964
|
-
if (linkPopoverOpenRef.current || document.documentElement.hasAttribute("data-ohw-section-picking")) {
|
|
17134
|
+
if (linkPopoverOpenRef.current || floatingPanelOpenRef.current && isPointOverFloatingPanel(clientX, clientY) || document.documentElement.hasAttribute("data-ohw-section-picking")) {
|
|
15965
17135
|
if (activeStateElRef.current) {
|
|
15966
17136
|
activeStateElRef.current.removeAttribute("data-ohw-state-hovered");
|
|
15967
17137
|
activeStateElRef.current = null;
|
|
@@ -16029,6 +17199,19 @@ function OhhwellsBridge() {
|
|
|
16029
17199
|
};
|
|
16030
17200
|
const handleMouseMove = (e) => {
|
|
16031
17201
|
const { clientX, clientY } = e;
|
|
17202
|
+
if (document.documentElement.hasAttribute("data-ohw-panel-dragging") || floatingPanelOpenRef.current && isPointOverFloatingPanel(clientX, clientY)) {
|
|
17203
|
+
hoveredItemElRef.current = null;
|
|
17204
|
+
setHoveredItemRect(null);
|
|
17205
|
+
hoveredNavContainerRef.current = null;
|
|
17206
|
+
setHoveredNavContainerRect(null);
|
|
17207
|
+
siblingHintElRef.current = null;
|
|
17208
|
+
setSiblingHintRect(null);
|
|
17209
|
+
setSiblingHintRects([]);
|
|
17210
|
+
dismissImageHover();
|
|
17211
|
+
clearImageHover();
|
|
17212
|
+
setSectionGap(null);
|
|
17213
|
+
return;
|
|
17214
|
+
}
|
|
16032
17215
|
probeSectionGapAt(clientX, clientY);
|
|
16033
17216
|
probeImageAt(clientX, clientY);
|
|
16034
17217
|
probeHoverCardsAt(clientX, clientY);
|
|
@@ -16037,6 +17220,11 @@ function OhhwellsBridge() {
|
|
|
16037
17220
|
if (e.data?.type !== "ow:pointer-sync") return;
|
|
16038
17221
|
const { clientX, clientY } = e.data;
|
|
16039
17222
|
if (typeof clientX !== "number" || typeof clientY !== "number") return;
|
|
17223
|
+
if (document.documentElement.hasAttribute("data-ohw-panel-dragging") || floatingPanelOpenRef.current && isPointOverFloatingPanel(clientX, clientY)) {
|
|
17224
|
+
dismissImageHover();
|
|
17225
|
+
clearImageHover();
|
|
17226
|
+
return;
|
|
17227
|
+
}
|
|
16040
17228
|
probeSectionGapAt(clientX, clientY);
|
|
16041
17229
|
probeImageAt(clientX, clientY);
|
|
16042
17230
|
probeHoverCardsAt(clientX, clientY);
|
|
@@ -16286,6 +17474,15 @@ function OhhwellsBridge() {
|
|
|
16286
17474
|
aiSectionsRef.current = content[AI_SECTIONS_KEY];
|
|
16287
17475
|
applyAiSectionsToDom(parseAiSectionsState(content[AI_SECTIONS_KEY]));
|
|
16288
17476
|
}
|
|
17477
|
+
if (typeof content[BRAND_KIT_KEY] === "string") {
|
|
17478
|
+
brandKitRef.current = content[BRAND_KIT_KEY];
|
|
17479
|
+
applyBrandToDom(parseBrandKit(content[BRAND_KIT_KEY]));
|
|
17480
|
+
}
|
|
17481
|
+
if (typeof content[STYLE_STORE_KEY] === "string") {
|
|
17482
|
+
stylesRef.current = content[STYLE_STORE_KEY];
|
|
17483
|
+
applyStylesToDom(parseStyleStore(content[STYLE_STORE_KEY]));
|
|
17484
|
+
}
|
|
17485
|
+
applyBrandChrome(content);
|
|
16289
17486
|
let sectionsJson = null;
|
|
16290
17487
|
for (const [key, val] of Object.entries(content)) {
|
|
16291
17488
|
if (key === "__ohw_sections") {
|
|
@@ -16293,6 +17490,11 @@ function OhhwellsBridge() {
|
|
|
16293
17490
|
continue;
|
|
16294
17491
|
}
|
|
16295
17492
|
if (key === AI_SECTIONS_KEY) continue;
|
|
17493
|
+
if (key === LOGO_PLACEHOLDER_KEY) continue;
|
|
17494
|
+
if (LOGO_IMAGE_KEYS.includes(key) && !String(val ?? "").trim()) continue;
|
|
17495
|
+
if (key === BRAND_KIT_KEY) continue;
|
|
17496
|
+
if (key === STYLE_STORE_KEY) continue;
|
|
17497
|
+
if (BRAND_CHROME_KEYS.has(key)) continue;
|
|
16296
17498
|
if (applyVideoSettingNode(key, val)) continue;
|
|
16297
17499
|
if (applyCarouselNode(key, val)) continue;
|
|
16298
17500
|
document.querySelectorAll(`[data-ohw-key="${key}"]`).forEach((el) => {
|
|
@@ -16312,6 +17514,8 @@ function OhhwellsBridge() {
|
|
|
16312
17514
|
});
|
|
16313
17515
|
applyLinkByKey(key, val);
|
|
16314
17516
|
}
|
|
17517
|
+
applyLogoFromContent(content);
|
|
17518
|
+
applyLogoSizes(content);
|
|
16315
17519
|
if (sectionsJson) {
|
|
16316
17520
|
initSectionsFromContent({ __ohw_sections: sectionsJson }, true);
|
|
16317
17521
|
sectionsLoadedRef.current = true;
|
|
@@ -16327,6 +17531,58 @@ function OhhwellsBridge() {
|
|
|
16327
17531
|
if (hydratedHeight > 50) postToParentRef.current({ type: "ow:height", height: hydratedHeight });
|
|
16328
17532
|
postToParentRef.current({ type: "ow:hydrate-done" });
|
|
16329
17533
|
};
|
|
17534
|
+
const handleUpdateLogoIdentity = (e) => {
|
|
17535
|
+
if (e.data?.type !== "ow:update-logo-identity") return;
|
|
17536
|
+
const rawText = typeof e.data.text === "string" ? e.data.text : "";
|
|
17537
|
+
const alt = typeof e.data.alt === "string" ? e.data.alt : rawText;
|
|
17538
|
+
const href = typeof e.data.href === "string" ? e.data.href : void 0;
|
|
17539
|
+
const imageProvided = "image" in e.data;
|
|
17540
|
+
const imageUrl = imageProvided && typeof e.data.image === "string" && e.data.image.trim() ? e.data.image.trim() : imageProvided ? null : void 0;
|
|
17541
|
+
let isPlaceholder = e.data.isPlaceholder !== false;
|
|
17542
|
+
if (imageUrl) isPlaceholder = false;
|
|
17543
|
+
else if (imageProvided && imageUrl === null) {
|
|
17544
|
+
isPlaceholder = e.data.isPlaceholder === true || !rawText.trim() || resolveLogoDisplayText(rawText) === PLACEHOLDER_BUSINESS_NAME;
|
|
17545
|
+
}
|
|
17546
|
+
const display = applyLogoIdentity(rawText, isPlaceholder);
|
|
17547
|
+
const displayAlt = resolveLogoDisplayText(alt || display);
|
|
17548
|
+
if (imageUrl !== void 0) {
|
|
17549
|
+
applyLogoImage(imageUrl, displayAlt);
|
|
17550
|
+
} else {
|
|
17551
|
+
for (const key of LOGO_IMAGE_KEYS) {
|
|
17552
|
+
document.querySelectorAll(`[data-ohw-key="${key}"]`).forEach((el) => {
|
|
17553
|
+
const img = el instanceof HTMLImageElement ? el : el.querySelector("img");
|
|
17554
|
+
if (img) img.alt = displayAlt;
|
|
17555
|
+
});
|
|
17556
|
+
}
|
|
17557
|
+
}
|
|
17558
|
+
if (href !== void 0) {
|
|
17559
|
+
applyLogoHref(href);
|
|
17560
|
+
applyLinkByKey("nav-logo-href", href);
|
|
17561
|
+
applyLinkByKey("footer-logo-href", href);
|
|
17562
|
+
applyLinkByKey("logo-href", href);
|
|
17563
|
+
}
|
|
17564
|
+
const nodes = [
|
|
17565
|
+
...LOGO_TEXT_KEYS.map((key) => ({ key, text: display })),
|
|
17566
|
+
{ key: LOGO_PLACEHOLDER_KEY, text: isPlaceholder ? "true" : "false" },
|
|
17567
|
+
{ key: LOGO_ALT_KEY, text: displayAlt }
|
|
17568
|
+
];
|
|
17569
|
+
if (imageUrl !== void 0) {
|
|
17570
|
+
if (imageUrl) {
|
|
17571
|
+
for (const key of LOGO_IMAGE_KEYS) nodes.push({ key, text: imageUrl });
|
|
17572
|
+
} else {
|
|
17573
|
+
for (const key of LOGO_IMAGE_KEYS) nodes.push({ key, text: "" });
|
|
17574
|
+
}
|
|
17575
|
+
}
|
|
17576
|
+
if (href !== void 0) {
|
|
17577
|
+
for (const key of LOGO_HREF_KEYS) nodes.push({ key, text: href.trim() || "/" });
|
|
17578
|
+
}
|
|
17579
|
+
editContentRef.current = {
|
|
17580
|
+
...editContentRef.current,
|
|
17581
|
+
...Object.fromEntries(nodes.map(({ key, text }) => [key, text]))
|
|
17582
|
+
};
|
|
17583
|
+
applyLogoSizes(editContentRef.current);
|
|
17584
|
+
postToParentRef.current({ type: "ow:change", nodes });
|
|
17585
|
+
};
|
|
16330
17586
|
window.addEventListener("message", handleHydrate);
|
|
16331
17587
|
const postAiSectionsChanged = () => {
|
|
16332
17588
|
postToParentRef.current({
|
|
@@ -16340,7 +17596,10 @@ function OhhwellsBridge() {
|
|
|
16340
17596
|
const payload = e.data.payload;
|
|
16341
17597
|
if (!payload || typeof payload.id !== "string" || !isRenderableTree(payload.tree)) return;
|
|
16342
17598
|
const previous = aiSectionsRef.current;
|
|
16343
|
-
const nextState = applyTreeToState(parseAiSectionsState(previous),
|
|
17599
|
+
const nextState = applyTreeToState(parseAiSectionsState(previous), {
|
|
17600
|
+
...payload,
|
|
17601
|
+
path: payload.path ?? window.location.pathname
|
|
17602
|
+
});
|
|
16344
17603
|
const nextValue = serializeAiSectionsState(nextState);
|
|
16345
17604
|
aiSectionsRef.current = nextValue;
|
|
16346
17605
|
applyAiSectionsToDom(nextState);
|
|
@@ -16377,12 +17636,42 @@ function OhhwellsBridge() {
|
|
|
16377
17636
|
const value = typeof e.data.value === "string" ? e.data.value : "";
|
|
16378
17637
|
aiSectionsRef.current = value;
|
|
16379
17638
|
applyAiSectionsToDom(parseAiSectionsState(value));
|
|
17639
|
+
applyStylesToDom(parseStyleStore(stylesRef.current));
|
|
16380
17640
|
const restoredHeight = document.documentElement.scrollHeight;
|
|
16381
17641
|
if (restoredHeight > 50) postToParentRef.current({ type: "ow:height", height: restoredHeight });
|
|
16382
17642
|
postToParentRef.current({ type: "ow:change", nodes: [{ key: AI_SECTIONS_KEY, text: value }] });
|
|
16383
17643
|
postAiSectionsChanged();
|
|
16384
17644
|
};
|
|
16385
17645
|
window.addEventListener("message", handleAiSetSections);
|
|
17646
|
+
const handleAiSetBrand = (e) => {
|
|
17647
|
+
if (e.data?.type !== "ow:ai-set-brand") return;
|
|
17648
|
+
const value = typeof e.data.value === "string" ? e.data.value : "";
|
|
17649
|
+
const previous = brandKitRef.current;
|
|
17650
|
+
brandKitRef.current = value;
|
|
17651
|
+
applyBrandToDom(parseBrandKit(value));
|
|
17652
|
+
if (aiSectionsRef.current) applyAiSectionsToDom(parseAiSectionsState(aiSectionsRef.current));
|
|
17653
|
+
applyStylesToDom(parseStyleStore(stylesRef.current));
|
|
17654
|
+
postToParentRef.current({ type: "ow:change", nodes: [{ key: BRAND_KIT_KEY, text: value }] });
|
|
17655
|
+
postToParentRef.current({ type: "ow:ai-brand-applied", previous, value });
|
|
17656
|
+
};
|
|
17657
|
+
window.addEventListener("message", handleAiSetBrand);
|
|
17658
|
+
const handleAiSetStyles = (e) => {
|
|
17659
|
+
if (e.data?.type !== "ow:ai-set-styles") return;
|
|
17660
|
+
const value = typeof e.data.value === "string" ? e.data.value : "";
|
|
17661
|
+
const previous = stylesRef.current;
|
|
17662
|
+
stylesRef.current = value;
|
|
17663
|
+
applyStylesToDom(parseStyleStore(value));
|
|
17664
|
+
postToParentRef.current({ type: "ow:change", nodes: [{ key: STYLE_STORE_KEY, text: value }] });
|
|
17665
|
+
postToParentRef.current({ type: "ow:ai-styles-applied", previous, value });
|
|
17666
|
+
};
|
|
17667
|
+
window.addEventListener("message", handleAiSetStyles);
|
|
17668
|
+
const handleGetBrand = (e) => {
|
|
17669
|
+
if (e.data?.type !== "ow:get-brand") return;
|
|
17670
|
+
const template = deriveTemplateBrand();
|
|
17671
|
+
const value = brandKitRef.current || (template ? JSON.stringify(template) : "");
|
|
17672
|
+
postToParentRef.current({ type: "ow:brand-value", value });
|
|
17673
|
+
};
|
|
17674
|
+
window.addEventListener("message", handleGetBrand);
|
|
16386
17675
|
const handleDeactivate = (e) => {
|
|
16387
17676
|
if (e.data?.type !== "ow:deactivate") return;
|
|
16388
17677
|
if (Date.now() < linkPopoverGraceUntilRef.current) return;
|
|
@@ -16391,6 +17680,12 @@ function OhhwellsBridge() {
|
|
|
16391
17680
|
closeLinkPopoverRef.current();
|
|
16392
17681
|
return;
|
|
16393
17682
|
}
|
|
17683
|
+
if (floatingPanelOpenRef.current) {
|
|
17684
|
+
setFloatingPanelRef.current(null);
|
|
17685
|
+
deselectRef.current();
|
|
17686
|
+
deactivateRef.current();
|
|
17687
|
+
return;
|
|
17688
|
+
}
|
|
16394
17689
|
deselectRef.current();
|
|
16395
17690
|
deactivateRef.current();
|
|
16396
17691
|
};
|
|
@@ -16444,6 +17739,10 @@ function OhhwellsBridge() {
|
|
|
16444
17739
|
return;
|
|
16445
17740
|
}
|
|
16446
17741
|
if (selectedElRef.current) {
|
|
17742
|
+
if (toolbarVariantRef.current === "logo") {
|
|
17743
|
+
deselectRef.current();
|
|
17744
|
+
return;
|
|
17745
|
+
}
|
|
16447
17746
|
if (toolbarVariantRef.current === "select-frame") {
|
|
16448
17747
|
const parent2 = getNavigationSelectionParent(selectedElRef.current);
|
|
16449
17748
|
if (parent2 && isNavigationContainer(parent2) && isFooterLinksContainer(parent2) && !isFooterLinksContainer(selectedElRef.current)) {
|
|
@@ -16483,6 +17782,10 @@ function OhhwellsBridge() {
|
|
|
16483
17782
|
return;
|
|
16484
17783
|
}
|
|
16485
17784
|
if (e.key === "Escape" && selectedElRef.current && !activeElRef.current) {
|
|
17785
|
+
if (toolbarVariantRef.current === "logo") {
|
|
17786
|
+
deselectRef.current();
|
|
17787
|
+
return;
|
|
17788
|
+
}
|
|
16486
17789
|
if (toolbarVariantRef.current === "select-frame") {
|
|
16487
17790
|
const parent2 = getNavigationSelectionParent(selectedElRef.current);
|
|
16488
17791
|
if (parent2 && isNavigationContainer(parent2) && isFooterLinksContainer(parent2) && !isFooterLinksContainer(selectedElRef.current)) {
|
|
@@ -16560,7 +17863,8 @@ function OhhwellsBridge() {
|
|
|
16560
17863
|
const handleScroll = () => {
|
|
16561
17864
|
const focusEl = activeElRef.current ?? selectedElRef.current;
|
|
16562
17865
|
if (focusEl) {
|
|
16563
|
-
const
|
|
17866
|
+
const measureEl = activeElRef.current ? getEditMeasureEl(activeElRef.current) : toolbarVariantRef.current === "logo" ? null : focusEl;
|
|
17867
|
+
const r2 = measureEl ? measureEl.getBoundingClientRect() : toolbarVariantRef.current === "logo" ? getLogoInteractionRect(focusEl) : focusEl.getBoundingClientRect();
|
|
16564
17868
|
applyToolbarPos(r2);
|
|
16565
17869
|
setToolbarRect(r2);
|
|
16566
17870
|
setMaxBadge((prev) => prev && activeElRef.current ? { ...prev, rect: r2 } : prev);
|
|
@@ -16570,7 +17874,9 @@ function OhhwellsBridge() {
|
|
|
16570
17874
|
setToggleState((prev) => prev ? { ...prev, rect } : null);
|
|
16571
17875
|
}
|
|
16572
17876
|
if (hoveredItemElRef.current) {
|
|
16573
|
-
|
|
17877
|
+
const hoverEl = hoveredItemElRef.current;
|
|
17878
|
+
const logo = getLogoElement(hoverEl);
|
|
17879
|
+
setHoveredItemRect(logo ? getLogoInteractionRect(logo) : hoverEl.getBoundingClientRect());
|
|
16574
17880
|
}
|
|
16575
17881
|
if (hoveredNavContainerRef.current) {
|
|
16576
17882
|
setHoveredNavContainerRect(hoveredNavContainerRef.current.getBoundingClientRect());
|
|
@@ -16614,6 +17920,12 @@ function OhhwellsBridge() {
|
|
|
16614
17920
|
if (aiSectionsRef.current) {
|
|
16615
17921
|
nodes.push({ key: AI_SECTIONS_KEY, type: "sections", text: aiSectionsRef.current });
|
|
16616
17922
|
}
|
|
17923
|
+
if (stylesRef.current) {
|
|
17924
|
+
nodes.push({ key: STYLE_STORE_KEY, type: "styles", text: stylesRef.current });
|
|
17925
|
+
}
|
|
17926
|
+
if (brandKitRef.current) {
|
|
17927
|
+
nodes.push({ key: BRAND_KIT_KEY, type: "brand", text: brandKitRef.current });
|
|
17928
|
+
}
|
|
16617
17929
|
postToParentRef.current({ type: "ow:save-result", nodes });
|
|
16618
17930
|
};
|
|
16619
17931
|
const handleInsertSection = (e) => {
|
|
@@ -16624,8 +17936,12 @@ function OhhwellsBridge() {
|
|
|
16624
17936
|
if (inserted) {
|
|
16625
17937
|
const tracker = getSectionsTracker();
|
|
16626
17938
|
postToParentRef.current({ type: "ow:change", nodes: [{ key: "__ohw_sections", text: tracker.textContent ?? "[]" }] });
|
|
16627
|
-
const
|
|
16628
|
-
|
|
17939
|
+
const reportHeight = () => {
|
|
17940
|
+
const h = document.body.scrollHeight;
|
|
17941
|
+
if (h > 50) postToParentRef.current({ type: "ow:height", height: h });
|
|
17942
|
+
};
|
|
17943
|
+
reportHeight();
|
|
17944
|
+
setTimeout(reportHeight, 500);
|
|
16629
17945
|
}
|
|
16630
17946
|
};
|
|
16631
17947
|
const handleSwitchSchedule = (e) => {
|
|
@@ -16818,13 +18134,17 @@ function OhhwellsBridge() {
|
|
|
16818
18134
|
if (e.data?.type !== "ow:parent-scroll") return;
|
|
16819
18135
|
const { iframeOffsetTop, headerH, canvasH } = e.data;
|
|
16820
18136
|
parentScrollRef.current = { iframeOffsetTop, headerH, canvasH };
|
|
18137
|
+
if (floatingPanelOpenRef.current) {
|
|
18138
|
+
setParentScrollSnap({ iframeOffsetTop, headerH, canvasH });
|
|
18139
|
+
}
|
|
16821
18140
|
if (visibleViewportRef.current) {
|
|
16822
18141
|
applyVisibleViewport(visibleViewportRef.current, parentScrollRef.current);
|
|
16823
18142
|
}
|
|
16824
18143
|
const focusEl = activeElRef.current ?? selectedElRef.current;
|
|
16825
18144
|
if (focusEl) {
|
|
16826
|
-
const measureEl = activeElRef.current ? getEditMeasureEl(activeElRef.current) : focusEl;
|
|
16827
|
-
|
|
18145
|
+
const measureEl = activeElRef.current ? getEditMeasureEl(activeElRef.current) : toolbarVariantRef.current === "logo" ? null : focusEl;
|
|
18146
|
+
const r2 = measureEl ? measureEl.getBoundingClientRect() : toolbarVariantRef.current === "logo" ? getLogoInteractionRect(focusEl) : focusEl.getBoundingClientRect();
|
|
18147
|
+
applyToolbarPos(r2);
|
|
16828
18148
|
}
|
|
16829
18149
|
};
|
|
16830
18150
|
const handleClickAt = (e) => {
|
|
@@ -16849,6 +18169,25 @@ function OhhwellsBridge() {
|
|
|
16849
18169
|
postToParentRef.current({ type: "ow:image-pick", key: stateCardImage.dataset.ohwKey ?? "", elementType: stateCardImage.dataset.ohwEditable ?? "image" });
|
|
16850
18170
|
return;
|
|
16851
18171
|
}
|
|
18172
|
+
const logoAtPoint = Array.from(
|
|
18173
|
+
document.querySelectorAll('[data-ohw-role="logo"], [data-ohw-logo]')
|
|
18174
|
+
).map((el) => getLogoElement(el)).find((logo) => {
|
|
18175
|
+
if (!logo) return false;
|
|
18176
|
+
const r2 = logo.getBoundingClientRect();
|
|
18177
|
+
return clientX >= r2.left && clientX <= r2.right && clientY >= r2.top && clientY <= r2.bottom;
|
|
18178
|
+
});
|
|
18179
|
+
if (logoAtPoint) {
|
|
18180
|
+
if (!logoHasUploadedImage(logoAtPoint)) {
|
|
18181
|
+
deselectRef.current();
|
|
18182
|
+
deactivateRef.current();
|
|
18183
|
+
const identity = readLogoIdentityFromDom();
|
|
18184
|
+
postToParentRef.current({ type: "ow:open-logo-settings", ...identity });
|
|
18185
|
+
return;
|
|
18186
|
+
}
|
|
18187
|
+
selectLogoRef.current(logoAtPoint);
|
|
18188
|
+
openLogoSizePanelRef.current(logoAtPoint);
|
|
18189
|
+
return;
|
|
18190
|
+
}
|
|
16852
18191
|
const textEditable = Array.from(
|
|
16853
18192
|
document.querySelectorAll(NON_MEDIA_SELECTOR)
|
|
16854
18193
|
).find((el) => {
|
|
@@ -16920,6 +18259,14 @@ function OhhwellsBridge() {
|
|
|
16920
18259
|
window.addEventListener("message", handleParentScroll);
|
|
16921
18260
|
window.addEventListener("message", handlePointerSync);
|
|
16922
18261
|
window.addEventListener("message", handleClickAt);
|
|
18262
|
+
window.addEventListener("message", handleUpdateLogoIdentity);
|
|
18263
|
+
const handleViewMode = (e) => {
|
|
18264
|
+
if (e.data?.type !== "ow:view-mode") return;
|
|
18265
|
+
const mode = e.data.mode === "Mobile" || e.data.mode === "mobile" ? "mobile" : "desktop";
|
|
18266
|
+
setEditorViewport(mode);
|
|
18267
|
+
applyLogoSizes(editContentRef.current);
|
|
18268
|
+
};
|
|
18269
|
+
window.addEventListener("message", handleViewMode);
|
|
16923
18270
|
const handleViewportResize = () => {
|
|
16924
18271
|
if (visibleViewportRef.current) {
|
|
16925
18272
|
applyVisibleViewport(visibleViewportRef.current, parentScrollRef.current);
|
|
@@ -16975,10 +18322,15 @@ function OhhwellsBridge() {
|
|
|
16975
18322
|
window.removeEventListener("resize", handleViewportResize);
|
|
16976
18323
|
window.removeEventListener("message", handlePointerSync);
|
|
16977
18324
|
window.removeEventListener("message", handleClickAt);
|
|
18325
|
+
window.removeEventListener("message", handleUpdateLogoIdentity);
|
|
18326
|
+
window.removeEventListener("message", handleViewMode);
|
|
16978
18327
|
window.removeEventListener("message", handleHydrate);
|
|
16979
18328
|
window.removeEventListener("message", handleAiApplyTree);
|
|
16980
18329
|
window.removeEventListener("message", handleAiDeleteSection);
|
|
16981
18330
|
window.removeEventListener("message", handleAiSetSections);
|
|
18331
|
+
window.removeEventListener("message", handleAiSetBrand);
|
|
18332
|
+
window.removeEventListener("message", handleAiSetStyles);
|
|
18333
|
+
window.removeEventListener("message", handleGetBrand);
|
|
16982
18334
|
window.removeEventListener("message", handleDeactivate);
|
|
16983
18335
|
window.removeEventListener("message", handleToastAction);
|
|
16984
18336
|
window.removeEventListener("message", handleUiEscape);
|
|
@@ -17004,7 +18356,7 @@ function OhhwellsBridge() {
|
|
|
17004
18356
|
if (footerDragRef.current) return;
|
|
17005
18357
|
const target = e.target;
|
|
17006
18358
|
if (!target) return;
|
|
17007
|
-
if (target.closest('[data-ohw-drag-handle-container], [data-slot="drag-handle"], [data-ohw-toolbar], [data-ohw-item-toolbar-anchor], [data-ohw-link-popover-root]')) {
|
|
18359
|
+
if (target.closest('[data-ohw-drag-handle-container], [data-slot="drag-handle"], [data-ohw-toolbar], [data-ohw-item-toolbar-anchor], [data-ohw-link-popover-root], [data-ohw-floating-panel]')) {
|
|
17008
18360
|
return;
|
|
17009
18361
|
}
|
|
17010
18362
|
if (target.closest("[data-ohw-item-drag-surface]")) return;
|
|
@@ -17182,7 +18534,7 @@ function OhhwellsBridge() {
|
|
|
17182
18534
|
postToParent2({
|
|
17183
18535
|
type: "ow:ready",
|
|
17184
18536
|
version: "1",
|
|
17185
|
-
bridgeVersion: "0.1.
|
|
18537
|
+
bridgeVersion: "0.1.60",
|
|
17186
18538
|
path: pathname,
|
|
17187
18539
|
nodes: collectEditableNodes(editContentRef.current),
|
|
17188
18540
|
sections
|
|
@@ -17577,10 +18929,10 @@ function OhhwellsBridge() {
|
|
|
17577
18929
|
[postToParent2]
|
|
17578
18930
|
);
|
|
17579
18931
|
return bridgeRoot ? (0, import_react_dom4.createPortal)(
|
|
17580
|
-
/* @__PURE__ */ (0,
|
|
17581
|
-
/* @__PURE__ */ (0,
|
|
17582
|
-
isEditMode && /* @__PURE__ */ (0,
|
|
17583
|
-
Object.entries(uploadingRects).map(([key, { rect, fadingOut }]) => /* @__PURE__ */ (0,
|
|
18932
|
+
/* @__PURE__ */ (0, import_jsx_runtime33.jsxs)(import_jsx_runtime33.Fragment, { children: [
|
|
18933
|
+
/* @__PURE__ */ (0, import_jsx_runtime33.jsx)("div", { ref: attachVisibleViewport, "data-ohw-visible-viewport": "", "aria-hidden": true }),
|
|
18934
|
+
isEditMode && /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(AiSectionOverlay, { postToParent: postToParent2, apiRef: aiSectionApiRef }),
|
|
18935
|
+
Object.entries(uploadingRects).map(([key, { rect, fadingOut }]) => /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
|
|
17584
18936
|
MediaOverlay,
|
|
17585
18937
|
{
|
|
17586
18938
|
hover: { key, rect, elementType: "image", isDragOver: false, hasTextOverlap: false },
|
|
@@ -17591,7 +18943,7 @@ function OhhwellsBridge() {
|
|
|
17591
18943
|
},
|
|
17592
18944
|
`uploading-${key}`
|
|
17593
18945
|
)),
|
|
17594
|
-
mediaHover && !(mediaHover.key in uploadingRects) && /* @__PURE__ */ (0,
|
|
18946
|
+
mediaHover && !(mediaHover.key in uploadingRects) && /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
|
|
17595
18947
|
MediaOverlay,
|
|
17596
18948
|
{
|
|
17597
18949
|
hover: mediaHover,
|
|
@@ -17600,11 +18952,11 @@ function OhhwellsBridge() {
|
|
|
17600
18952
|
onVideoSettingsChange: handleVideoSettingsChange
|
|
17601
18953
|
}
|
|
17602
18954
|
),
|
|
17603
|
-
carouselHover && !linkPopover && !isItemDragging && /* @__PURE__ */ (0,
|
|
17604
|
-
siblingHintRect && !linkPopover && !isItemDragging && siblingHintRects.length === 0 && /* @__PURE__ */ (0,
|
|
17605
|
-
siblingHintRects.length > 0 && !linkPopover && !isItemDragging && siblingHintRects.map((rect, i) => /* @__PURE__ */ (0,
|
|
17606
|
-
isItemDragging && draggedItemRect && selectedElRef.current !== footerDragRef.current?.draggedEl && selectedElRef.current !== navDragRef.current?.draggedEl && /* @__PURE__ */ (0,
|
|
17607
|
-
isItemDragging && footerDropSlots.map((slot, i) => /* @__PURE__ */ (0,
|
|
18955
|
+
carouselHover && !linkPopover && !isItemDragging && /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(CarouselOverlay, { hover: carouselHover, onEdit: handleEditCarousel }),
|
|
18956
|
+
siblingHintRect && !linkPopover && !isItemDragging && siblingHintRects.length === 0 && /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(ItemInteractionLayer, { rect: siblingHintRect, state: "sibling-hint" }),
|
|
18957
|
+
siblingHintRects.length > 0 && !linkPopover && !isItemDragging && siblingHintRects.map((rect, i) => /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(ItemInteractionLayer, { rect, state: "sibling-hint" }, `sibling-hint-${i}`)),
|
|
18958
|
+
isItemDragging && draggedItemRect && selectedElRef.current !== footerDragRef.current?.draggedEl && selectedElRef.current !== navDragRef.current?.draggedEl && /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(ItemInteractionLayer, { rect: draggedItemRect, state: "dragging" }),
|
|
18959
|
+
isItemDragging && footerDropSlots.map((slot, i) => /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
|
|
17608
18960
|
"div",
|
|
17609
18961
|
{
|
|
17610
18962
|
className: "pointer-events-none fixed z-2147483646",
|
|
@@ -17614,7 +18966,7 @@ function OhhwellsBridge() {
|
|
|
17614
18966
|
width: slot.width,
|
|
17615
18967
|
height: slot.height
|
|
17616
18968
|
},
|
|
17617
|
-
children: /* @__PURE__ */ (0,
|
|
18969
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
|
|
17618
18970
|
DropIndicator,
|
|
17619
18971
|
{
|
|
17620
18972
|
direction: slot.direction,
|
|
@@ -17625,7 +18977,7 @@ function OhhwellsBridge() {
|
|
|
17625
18977
|
},
|
|
17626
18978
|
`footer-drop-${slot.direction}-${slot.columnIndex}-${slot.insertIndex}-${i}`
|
|
17627
18979
|
)),
|
|
17628
|
-
isItemDragging && navDropSlots.map((slot, i) => /* @__PURE__ */ (0,
|
|
18980
|
+
isItemDragging && navDropSlots.map((slot, i) => /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
|
|
17629
18981
|
"div",
|
|
17630
18982
|
{
|
|
17631
18983
|
className: "pointer-events-none fixed z-2147483646",
|
|
@@ -17635,7 +18987,7 @@ function OhhwellsBridge() {
|
|
|
17635
18987
|
width: slot.width,
|
|
17636
18988
|
height: slot.height
|
|
17637
18989
|
},
|
|
17638
|
-
children: /* @__PURE__ */ (0,
|
|
18990
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
|
|
17639
18991
|
DropIndicator,
|
|
17640
18992
|
{
|
|
17641
18993
|
direction: slot.direction,
|
|
@@ -17646,10 +18998,11 @@ function OhhwellsBridge() {
|
|
|
17646
18998
|
},
|
|
17647
18999
|
`nav-drop-${slot.direction}-${slot.parentId ?? "root"}-${slot.insertIndex}-${i}`
|
|
17648
19000
|
)),
|
|
17649
|
-
hoveredNavContainerRect && (toolbarVariant !== "select-frame" || isFooterFrameSelection) && !linkPopover && !isItemDragging && /* @__PURE__ */ (0,
|
|
17650
|
-
hoveredItemRect && !linkPopover && !hoveredNavContainerRect && !isItemDragging && hoveredItemElRef.current !== selectedElRef.current && /* @__PURE__ */ (0,
|
|
17651
|
-
|
|
17652
|
-
toolbarVariant === "select-frame" && toolbarRect && !linkPopover && !isItemDragging && !isFooterFrameSelection && selectedElRef.current &&
|
|
19001
|
+
hoveredNavContainerRect && (toolbarVariant !== "select-frame" || isFooterFrameSelection) && !linkPopover && !isItemDragging && /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(ItemInteractionLayer, { rect: hoveredNavContainerRect, state: "hover" }),
|
|
19002
|
+
hoveredItemRect && !linkPopover && !hoveredNavContainerRect && !isItemDragging && hoveredItemElRef.current !== selectedElRef.current && /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(ItemInteractionLayer, { rect: hoveredItemRect, state: "hover" }),
|
|
19003
|
+
hoveredTextRect && !isItemDragging && toolbarVariant !== "rich-text" && /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(ItemInteractionLayer, { rect: hoveredTextRect, state: "hover" }),
|
|
19004
|
+
toolbarVariant === "select-frame" && toolbarRect && !linkPopover && !isItemDragging && !isFooterFrameSelection && selectedElRef.current && isNavbarLinksContainer2(selectedElRef.current) && /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(NavbarContainerChrome, { rect: toolbarRect, onAdd: handleAddTopLevelNavItem }),
|
|
19005
|
+
toolbarVariant === "select-frame" && toolbarRect && !linkPopover && !isItemDragging && !isFooterFrameSelection && selectedElRef.current && isFooterLinksContainer(selectedElRef.current) && /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
|
|
17653
19006
|
FooterContainerChrome,
|
|
17654
19007
|
{
|
|
17655
19008
|
rect: toolbarRect,
|
|
@@ -17657,7 +19010,7 @@ function OhhwellsBridge() {
|
|
|
17657
19010
|
addDisabled: !canAddFooterColumn()
|
|
17658
19011
|
}
|
|
17659
19012
|
),
|
|
17660
|
-
toolbarRect && !linkPopover && (toolbarVariant === "link-action" || toolbarVariant === "select-frame") && /* @__PURE__ */ (0,
|
|
19013
|
+
toolbarRect && !linkPopover && (toolbarVariant === "link-action" || toolbarVariant === "select-frame" || toolbarVariant === "logo") && /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
|
|
17661
19014
|
ItemInteractionLayer,
|
|
17662
19015
|
{
|
|
17663
19016
|
rect: isItemDragging && draggedItemRect && (footerDragRef.current?.wasSelected || navDragRef.current?.wasSelected) ? draggedItemRect : toolbarRect,
|
|
@@ -17669,10 +19022,10 @@ function OhhwellsBridge() {
|
|
|
17669
19022
|
dragHandleLabel: reorderHrefKey ? `Reorder ${reorderHrefKey}` : "Reorder item",
|
|
17670
19023
|
onDragHandleDragStart: handleItemDragStart,
|
|
17671
19024
|
onDragHandleDragEnd: handleItemDragEnd,
|
|
17672
|
-
onItemPointerDown: handleItemChromePointerDown,
|
|
17673
|
-
onItemClick: handleItemChromeClick,
|
|
17674
|
-
itemDragSurface: !isFooterFrameSelection,
|
|
17675
|
-
toolbar: toolbarVariant === "link-action" && !isItemDragging || toolbarVariant === "select-frame" && (isFooterFrameSelection || selectedIsSocialsRow) && !isItemDragging ? /* @__PURE__ */ (0,
|
|
19025
|
+
onItemPointerDown: toolbarVariant === "logo" ? void 0 : handleItemChromePointerDown,
|
|
19026
|
+
onItemClick: toolbarVariant === "logo" ? void 0 : handleItemChromeClick,
|
|
19027
|
+
itemDragSurface: toolbarVariant !== "logo" && !isFooterFrameSelection,
|
|
19028
|
+
toolbar: toolbarVariant === "link-action" && !isItemDragging || toolbarVariant === "select-frame" && (isFooterFrameSelection || selectedIsSocialsRow) && !isItemDragging ? /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
|
|
17676
19029
|
ItemActionToolbar,
|
|
17677
19030
|
{
|
|
17678
19031
|
onEditLink: openLinkPopoverForSelected,
|
|
@@ -17688,7 +19041,10 @@ function OhhwellsBridge() {
|
|
|
17688
19041
|
onSelectParent: handleSelectParent,
|
|
17689
19042
|
onDuplicate: handleDuplicateSelected,
|
|
17690
19043
|
onDelete: handleDeleteSelected,
|
|
17691
|
-
addItemDisabled:
|
|
19044
|
+
addItemDisabled: isFooterFrameSelection && isFooterAddItemDisabled(selectedElRef.current) || selectedElRef.current !== null && (() => {
|
|
19045
|
+
const row = isSocialsRow(selectedElRef.current) ? selectedElRef.current : findSocialsRow(selectedElRef.current);
|
|
19046
|
+
return row ? !canAddSocialItem(row) : false;
|
|
19047
|
+
})(),
|
|
17692
19048
|
editLinkDisabled: false,
|
|
17693
19049
|
moreDisabled: false,
|
|
17694
19050
|
duplicateDisabled: isFooterFrameSelection || selectedIsSocialsRow,
|
|
@@ -17705,8 +19061,8 @@ function OhhwellsBridge() {
|
|
|
17705
19061
|
) : void 0
|
|
17706
19062
|
}
|
|
17707
19063
|
),
|
|
17708
|
-
toolbarRect && toolbarVariant === "rich-text" && !linkPopover && /* @__PURE__ */ (0,
|
|
17709
|
-
/* @__PURE__ */ (0,
|
|
19064
|
+
toolbarRect && toolbarVariant === "rich-text" && !linkPopover && /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)(import_jsx_runtime33.Fragment, { children: [
|
|
19065
|
+
/* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
|
|
17710
19066
|
EditGlowChrome,
|
|
17711
19067
|
{
|
|
17712
19068
|
rect: toolbarRect,
|
|
@@ -17716,7 +19072,7 @@ function OhhwellsBridge() {
|
|
|
17716
19072
|
hideHandle: isItemDragging
|
|
17717
19073
|
}
|
|
17718
19074
|
),
|
|
17719
|
-
/* @__PURE__ */ (0,
|
|
19075
|
+
/* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
|
|
17720
19076
|
FloatingToolbar,
|
|
17721
19077
|
{
|
|
17722
19078
|
rect: toolbarRect,
|
|
@@ -17729,7 +19085,7 @@ function OhhwellsBridge() {
|
|
|
17729
19085
|
}
|
|
17730
19086
|
)
|
|
17731
19087
|
] }),
|
|
17732
|
-
maxBadge && /* @__PURE__ */ (0,
|
|
19088
|
+
maxBadge && /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)(
|
|
17733
19089
|
"div",
|
|
17734
19090
|
{
|
|
17735
19091
|
"data-ohw-max-badge": "",
|
|
@@ -17755,7 +19111,7 @@ function OhhwellsBridge() {
|
|
|
17755
19111
|
]
|
|
17756
19112
|
}
|
|
17757
19113
|
),
|
|
17758
|
-
toggleState && !linkPopover && /* @__PURE__ */ (0,
|
|
19114
|
+
toggleState && !linkPopover && /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
|
|
17759
19115
|
StateToggle,
|
|
17760
19116
|
{
|
|
17761
19117
|
rect: toggleState.rect,
|
|
@@ -17764,15 +19120,15 @@ function OhhwellsBridge() {
|
|
|
17764
19120
|
onStateChange: handleStateChange
|
|
17765
19121
|
}
|
|
17766
19122
|
),
|
|
17767
|
-
sectionGap && !linkPopover && /* @__PURE__ */ (0,
|
|
19123
|
+
sectionGap && !linkPopover && /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)(
|
|
17768
19124
|
"div",
|
|
17769
19125
|
{
|
|
17770
19126
|
"data-ohw-section-insert-line": "",
|
|
17771
19127
|
className: "fixed left-0 w-full z-2147483646 flex items-center pointer-events-none",
|
|
17772
19128
|
style: { top: sectionGap.y, transform: "translateY(-50%)" },
|
|
17773
19129
|
children: [
|
|
17774
|
-
/* @__PURE__ */ (0,
|
|
17775
|
-
/* @__PURE__ */ (0,
|
|
19130
|
+
/* @__PURE__ */ (0, import_jsx_runtime33.jsx)("div", { className: "flex-1 bg-primary", style: { height: 3 } }),
|
|
19131
|
+
/* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
|
|
17776
19132
|
Badge,
|
|
17777
19133
|
{
|
|
17778
19134
|
className: "px-8 py-1 bg-primary hover:bg-primary text-primary-foreground text-xs font-medium shrink-0 rounded-full cursor-pointer pointer-events-auto",
|
|
@@ -17789,11 +19145,11 @@ function OhhwellsBridge() {
|
|
|
17789
19145
|
children: "Add Section"
|
|
17790
19146
|
}
|
|
17791
19147
|
),
|
|
17792
|
-
/* @__PURE__ */ (0,
|
|
19148
|
+
/* @__PURE__ */ (0, import_jsx_runtime33.jsx)("div", { className: "flex-1 bg-primary", style: { height: 3 } })
|
|
17793
19149
|
]
|
|
17794
19150
|
}
|
|
17795
19151
|
),
|
|
17796
|
-
linkPopover && dialogPortalContainer ? /* @__PURE__ */ (0,
|
|
19152
|
+
linkPopover && dialogPortalContainer ? /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
|
|
17797
19153
|
LinkPopover,
|
|
17798
19154
|
{
|
|
17799
19155
|
panelRef: linkPopoverPanelRef,
|
|
@@ -17810,7 +19166,7 @@ function OhhwellsBridge() {
|
|
|
17810
19166
|
},
|
|
17811
19167
|
linkPopover.key
|
|
17812
19168
|
) : null,
|
|
17813
|
-
floatingPanel && floatingPanel.kind === "socials-display" ? /* @__PURE__ */ (0,
|
|
19169
|
+
floatingPanel && floatingPanel.kind === "socials-display" ? /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
|
|
17814
19170
|
FloatingPanel,
|
|
17815
19171
|
{
|
|
17816
19172
|
open: true,
|
|
@@ -17820,7 +19176,7 @@ function OhhwellsBridge() {
|
|
|
17820
19176
|
onPositionChange: setFloatingPanelPos,
|
|
17821
19177
|
parentScroll: parentScrollSnap ?? parentScrollRef.current,
|
|
17822
19178
|
onClose: closeFloatingPanelOnly,
|
|
17823
|
-
children: /* @__PURE__ */ (0,
|
|
19179
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
|
|
17824
19180
|
SocialsDisplayPanel,
|
|
17825
19181
|
{
|
|
17826
19182
|
display: socialsDisplayFor(floatingPanel.row, editContentRef.current),
|
|
@@ -17831,11 +19187,115 @@ function OhhwellsBridge() {
|
|
|
17831
19187
|
}
|
|
17832
19188
|
)
|
|
17833
19189
|
}
|
|
19190
|
+
) : null,
|
|
19191
|
+
floatingPanel && floatingPanel.kind === "logo-size" && logoSizeDraft ? /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
|
|
19192
|
+
FloatingPanel,
|
|
19193
|
+
{
|
|
19194
|
+
open: true,
|
|
19195
|
+
title: floatingPanel.title,
|
|
19196
|
+
context: floatingPanel.context,
|
|
19197
|
+
position: floatingPanelPos,
|
|
19198
|
+
onPositionChange: setFloatingPanelPos,
|
|
19199
|
+
parentScroll: parentScrollSnap ?? parentScrollRef.current,
|
|
19200
|
+
onClose: closeFloatingPanelAndDeselect,
|
|
19201
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
|
|
19202
|
+
LogoSizePanel,
|
|
19203
|
+
{
|
|
19204
|
+
viewport: editorViewport,
|
|
19205
|
+
sizePx: editorViewport === "mobile" && !logoSizeDraft.mobileFollowing ? logoSizeDraft.mobilePx : logoSizeDraft.desktopPx,
|
|
19206
|
+
mobileFollowing: logoSizeDraft.mobileFollowing,
|
|
19207
|
+
onSizeChange: (px) => {
|
|
19208
|
+
const next = editorViewport === "mobile" ? { ...logoSizeDraft, mobilePx: px, mobileFollowing: false } : {
|
|
19209
|
+
...logoSizeDraft,
|
|
19210
|
+
desktopPx: px,
|
|
19211
|
+
mobilePx: logoSizeDraft.mobileFollowing ? px : logoSizeDraft.mobilePx
|
|
19212
|
+
};
|
|
19213
|
+
setLogoSizeDraft(next);
|
|
19214
|
+
persistLogoSizeDraft(floatingPanel.placement, next);
|
|
19215
|
+
},
|
|
19216
|
+
onCustomizeMobile: () => {
|
|
19217
|
+
const next = {
|
|
19218
|
+
...logoSizeDraft,
|
|
19219
|
+
mobileFollowing: false,
|
|
19220
|
+
mobilePx: logoSizeDraft.desktopPx
|
|
19221
|
+
};
|
|
19222
|
+
setLogoSizeDraft(next);
|
|
19223
|
+
persistLogoSizeDraft(floatingPanel.placement, next);
|
|
19224
|
+
},
|
|
19225
|
+
onResetMobile: () => {
|
|
19226
|
+
const next = {
|
|
19227
|
+
...logoSizeDraft,
|
|
19228
|
+
mobileFollowing: true,
|
|
19229
|
+
mobilePx: logoSizeDraft.desktopPx
|
|
19230
|
+
};
|
|
19231
|
+
setLogoSizeDraft(next);
|
|
19232
|
+
persistLogoSizeDraft(floatingPanel.placement, next);
|
|
19233
|
+
},
|
|
19234
|
+
onUpdateEverywhere: () => {
|
|
19235
|
+
const identity = readLogoIdentityFromDom();
|
|
19236
|
+
postToParent2({ type: "ow:open-logo-settings", ...identity });
|
|
19237
|
+
}
|
|
19238
|
+
}
|
|
19239
|
+
)
|
|
19240
|
+
}
|
|
17834
19241
|
) : null
|
|
17835
19242
|
] }),
|
|
17836
19243
|
bridgeRoot
|
|
17837
19244
|
) : null;
|
|
17838
19245
|
}
|
|
19246
|
+
|
|
19247
|
+
// src/ui/EmptySection.tsx
|
|
19248
|
+
var import_link = __toESM(require("next/link"), 1);
|
|
19249
|
+
var import_jsx_runtime34 = require("react/jsx-runtime");
|
|
19250
|
+
function EmptySection({ title, homeHref = "/", eyebrowKey, titleKey, subtitleKey }) {
|
|
19251
|
+
return /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)(import_jsx_runtime34.Fragment, { children: [
|
|
19252
|
+
/* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
|
|
19253
|
+
"p",
|
|
19254
|
+
{
|
|
19255
|
+
style: {
|
|
19256
|
+
fontFamily: "var(--brand-font-body)",
|
|
19257
|
+
fontSize: "0.75rem",
|
|
19258
|
+
fontWeight: 500,
|
|
19259
|
+
letterSpacing: "0.15em",
|
|
19260
|
+
textTransform: "uppercase",
|
|
19261
|
+
color: "var(--brand-accent)",
|
|
19262
|
+
marginBottom: "1.5rem"
|
|
19263
|
+
},
|
|
19264
|
+
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" }) })
|
|
19265
|
+
}
|
|
19266
|
+
),
|
|
19267
|
+
/* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
|
|
19268
|
+
"h1",
|
|
19269
|
+
{
|
|
19270
|
+
style: {
|
|
19271
|
+
fontFamily: "var(--brand-font-heading)",
|
|
19272
|
+
fontSize: "clamp(2rem, 3.5vw, 2.75rem)",
|
|
19273
|
+
lineHeight: 1.1,
|
|
19274
|
+
letterSpacing: "-0.025em",
|
|
19275
|
+
color: "var(--brand-text)",
|
|
19276
|
+
marginBottom: "1rem"
|
|
19277
|
+
},
|
|
19278
|
+
...titleKey ? { "data-ohw-editable": "text", "data-ohw-key": titleKey, "data-ohw-max-length": 80 } : {},
|
|
19279
|
+
children: title
|
|
19280
|
+
}
|
|
19281
|
+
),
|
|
19282
|
+
/* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
|
|
19283
|
+
"p",
|
|
19284
|
+
{
|
|
19285
|
+
style: {
|
|
19286
|
+
fontFamily: "var(--brand-font-body)",
|
|
19287
|
+
fontSize: "1rem",
|
|
19288
|
+
lineHeight: 1.7,
|
|
19289
|
+
fontWeight: 300,
|
|
19290
|
+
color: "var(--brand-text-muted)",
|
|
19291
|
+
maxWidth: "340px"
|
|
19292
|
+
},
|
|
19293
|
+
...subtitleKey ? { "data-ohw-editable": "text", "data-ohw-key": subtitleKey, "data-ohw-max-length": 160 } : {},
|
|
19294
|
+
children: "This page doesn't have any content yet."
|
|
19295
|
+
}
|
|
19296
|
+
)
|
|
19297
|
+
] });
|
|
19298
|
+
}
|
|
17839
19299
|
// Annotate the CommonJS export names for ESM import in node:
|
|
17840
19300
|
0 && (module.exports = {
|
|
17841
19301
|
AI_DEFAULT_BRAND,
|
|
@@ -17853,6 +19313,7 @@ function OhhwellsBridge() {
|
|
|
17853
19313
|
DropdownMenuItem,
|
|
17854
19314
|
DropdownMenuSeparator,
|
|
17855
19315
|
DropdownMenuTrigger,
|
|
19316
|
+
EmptySection,
|
|
17856
19317
|
ItemActionToolbar,
|
|
17857
19318
|
ItemInteractionLayer,
|
|
17858
19319
|
LinkEditorPanel,
|