@ohhwells/bridge 0.1.121 → 0.1.122-next.336
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 +2823 -468
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +46 -2
- package/dist/index.d.ts +46 -2
- package/dist/index.js +2821 -467
- package/dist/index.js.map +1 -1
- package/dist/pages.cjs +141 -0
- package/dist/pages.cjs.map +1 -0
- package/dist/pages.d.cts +45 -0
- package/dist/pages.d.ts +45 -0
- package/dist/pages.js +107 -0
- package/dist/pages.js.map +1 -0
- package/dist/styles.css +125 -8
- package/package.json +8 -3
package/dist/index.js
CHANGED
|
@@ -31,6 +31,10 @@ function enforceLinkHrefs() {
|
|
|
31
31
|
|
|
32
32
|
// src/lib/ai-tree.ts
|
|
33
33
|
var AI_TREE_SCHEMA_VERSIONS = [1];
|
|
34
|
+
var BUTTON_FILL_TOKENS = ["dark", "primary", "accent", "light"];
|
|
35
|
+
var BUTTON_STYLES = ["solid", "outline", "ghost"];
|
|
36
|
+
var BUTTON_RADII = ["square", "rounded", "pill"];
|
|
37
|
+
var BUTTON_SIZES = ["s", "m", "l"];
|
|
34
38
|
var AI_DEFAULT_BRAND = {
|
|
35
39
|
palette: { dark: "#0C0A09", primary: "#0078E5", accent: "#747271", light: "#ECECEB" },
|
|
36
40
|
fonts: {
|
|
@@ -290,6 +294,118 @@ var FONT_VARS = {
|
|
|
290
294
|
var BRAND_FONT_LINK_ID = "ohw-brand-fonts";
|
|
291
295
|
var CUSTOM_FONT_STYLE_ID = "ohw-brand-custom-fonts";
|
|
292
296
|
var CUSTOM_FONT_FORMATS = /* @__PURE__ */ new Set(["woff2", "woff", "truetype", "opentype"]);
|
|
297
|
+
var BUTTON_RADIUS_PX = {
|
|
298
|
+
square: 0,
|
|
299
|
+
rounded: AI_TREE_TOKENS.radiusButton,
|
|
300
|
+
pill: 999
|
|
301
|
+
};
|
|
302
|
+
var BUTTON_SIZE_SPEC = {
|
|
303
|
+
s: {
|
|
304
|
+
paddingX: `${AI_TREE_TOKENS.spacing4}px`,
|
|
305
|
+
paddingY: `${AI_TREE_TOKENS.spacing2}px`,
|
|
306
|
+
fontSize: "14px"
|
|
307
|
+
},
|
|
308
|
+
m: {
|
|
309
|
+
paddingX: `${AI_TREE_TOKENS.spacing6}px`,
|
|
310
|
+
paddingY: `${AI_TREE_TOKENS.spacing3}px`,
|
|
311
|
+
fontSize: `${AI_TREE_TOKENS.type.button.size}px`
|
|
312
|
+
},
|
|
313
|
+
l: {
|
|
314
|
+
paddingX: `${AI_TREE_TOKENS.spacing8}px`,
|
|
315
|
+
paddingY: `${AI_TREE_TOKENS.spacing4}px`,
|
|
316
|
+
fontSize: "18px"
|
|
317
|
+
}
|
|
318
|
+
};
|
|
319
|
+
var BUTTON_SIZE_SCALE = { s: 0.85, m: 1, l: 1.25 };
|
|
320
|
+
var roundHalf = (n) => Math.round(n * 2) / 2;
|
|
321
|
+
function measureTemplateButton(variant) {
|
|
322
|
+
const root = document.documentElement;
|
|
323
|
+
const el = document.querySelector(`.btn--${variant}, .btn-${variant}`);
|
|
324
|
+
if (!el) return null;
|
|
325
|
+
const sheet = document.getElementById(BUTTON_RULES_STYLE_ID);
|
|
326
|
+
const rules = sheet?.textContent ?? "";
|
|
327
|
+
const saved = BUTTON_VAR_NAMES.map((name) => [name, root.style.getPropertyValue(name)]);
|
|
328
|
+
if (sheet) sheet.textContent = "";
|
|
329
|
+
for (const [name] of saved) root.style.removeProperty(name);
|
|
330
|
+
const cs = getComputedStyle(el);
|
|
331
|
+
const base = {
|
|
332
|
+
fontSize: parseFloat(cs.fontSize),
|
|
333
|
+
top: parseFloat(cs.paddingTop),
|
|
334
|
+
right: parseFloat(cs.paddingRight),
|
|
335
|
+
bottom: parseFloat(cs.paddingBottom),
|
|
336
|
+
left: parseFloat(cs.paddingLeft)
|
|
337
|
+
};
|
|
338
|
+
if (sheet) sheet.textContent = rules;
|
|
339
|
+
for (const [name, value] of saved) if (value) root.style.setProperty(name, value);
|
|
340
|
+
return Object.values(base).every(Number.isFinite) && base.fontSize > 0 ? base : null;
|
|
341
|
+
}
|
|
342
|
+
function scaledButtonSize(size, base) {
|
|
343
|
+
if (!base) return BUTTON_SIZE_SPEC[size];
|
|
344
|
+
const k = BUTTON_SIZE_SCALE[size];
|
|
345
|
+
const px2 = (n) => `${roundHalf(n * k)}px`;
|
|
346
|
+
return {
|
|
347
|
+
// Each side scaled on its own, so a button with uneven padding (say, room for an icon on one
|
|
348
|
+
// side) keeps its shape; the x/y vars are the averages for templates that read those instead.
|
|
349
|
+
padding: `${px2(base.top)} ${px2(base.right)} ${px2(base.bottom)} ${px2(base.left)}`,
|
|
350
|
+
paddingX: px2((base.left + base.right) / 2),
|
|
351
|
+
paddingY: px2((base.top + base.bottom) / 2),
|
|
352
|
+
fontSize: `${roundHalf(base.fontSize * k)}px`
|
|
353
|
+
};
|
|
354
|
+
}
|
|
355
|
+
var BUTTON_VAR_ROLES = ["bg", "text", "border", "radius", "padding-x", "padding-y", "padding", "font-size"];
|
|
356
|
+
var BUTTON_VAR_NAMES = ["primary", "secondary"].flatMap(
|
|
357
|
+
(variant) => BUTTON_VAR_ROLES.map((role) => `--brand-button-${variant}-${role}`)
|
|
358
|
+
);
|
|
359
|
+
var ROLES_BY_FIELD = {
|
|
360
|
+
fill: ["bg"],
|
|
361
|
+
style: ["bg", "border"],
|
|
362
|
+
textColor: ["text"],
|
|
363
|
+
radius: ["radius"],
|
|
364
|
+
size: ["padding-x", "padding-y", "padding", "font-size"]
|
|
365
|
+
};
|
|
366
|
+
function touchedButtonRoles(variant, kit) {
|
|
367
|
+
if (!kit.touched) return new Set(BUTTON_VAR_ROLES);
|
|
368
|
+
const fields = kit.touched.buttons?.[variant] ?? [];
|
|
369
|
+
const outline = fields.includes("style") && kit.buttons?.[variant]?.style === "outline";
|
|
370
|
+
return new Set(
|
|
371
|
+
fields.flatMap((f) => {
|
|
372
|
+
if (outline && (f === "fill" || f === "style")) return ["border"];
|
|
373
|
+
return ROLES_BY_FIELD[f] ?? [];
|
|
374
|
+
})
|
|
375
|
+
);
|
|
376
|
+
}
|
|
377
|
+
function buttonPalette(kit) {
|
|
378
|
+
return kit.palette ?? {
|
|
379
|
+
dark: "var(--brand-text)",
|
|
380
|
+
primary: "var(--brand-primary)",
|
|
381
|
+
accent: "var(--brand-accent)",
|
|
382
|
+
light: "var(--brand-background)"
|
|
383
|
+
};
|
|
384
|
+
}
|
|
385
|
+
function buttonVariantVars(variant, style, roles, palette) {
|
|
386
|
+
const fill = palette[style.fill];
|
|
387
|
+
const text = palette[style.textColor];
|
|
388
|
+
const size = scaledButtonSize(style.size, roles.has("font-size") ? measureTemplateButton(variant) : null);
|
|
389
|
+
const { bg, border } = !roles.has("border") ? { bg: fill, border: "transparent" } : style.style === "outline" ? { bg: "transparent", border: fill } : style.style === "ghost" ? { bg: "transparent", border: "transparent" } : { bg: fill, border: "transparent" };
|
|
390
|
+
const all = {
|
|
391
|
+
[`--brand-button-${variant}-bg`]: bg,
|
|
392
|
+
[`--brand-button-${variant}-text`]: text,
|
|
393
|
+
[`--brand-button-${variant}-border`]: border,
|
|
394
|
+
[`--brand-button-${variant}-radius`]: `${BUTTON_RADIUS_PX[style.radius]}px`,
|
|
395
|
+
[`--brand-button-${variant}-padding-x`]: size.paddingX,
|
|
396
|
+
[`--brand-button-${variant}-padding-y`]: size.paddingY,
|
|
397
|
+
...size.padding ? { [`--brand-button-${variant}-padding`]: size.padding } : {},
|
|
398
|
+
[`--brand-button-${variant}-font-size`]: size.fontSize
|
|
399
|
+
};
|
|
400
|
+
const prefix = `--brand-button-${variant}-`;
|
|
401
|
+
return Object.fromEntries(Object.entries(all).filter(([name]) => roles.has(name.slice(prefix.length))));
|
|
402
|
+
}
|
|
403
|
+
function buttonStyleVars(kit) {
|
|
404
|
+
return {
|
|
405
|
+
...buttonVariantVars("primary", kit.buttons.primary, touchedButtonRoles("primary", kit), buttonPalette(kit)),
|
|
406
|
+
...buttonVariantVars("secondary", kit.buttons.secondary, touchedButtonRoles("secondary", kit), buttonPalette(kit))
|
|
407
|
+
};
|
|
408
|
+
}
|
|
293
409
|
function brandColorVars(palette) {
|
|
294
410
|
const { dark, primary, accent, light } = palette;
|
|
295
411
|
const mix = (a, aPct, b) => `color-mix(in srgb, ${a} ${aPct}%, ${b})`;
|
|
@@ -317,6 +433,11 @@ function brandColorVars(palette) {
|
|
|
317
433
|
"--brand-on-primary": light
|
|
318
434
|
};
|
|
319
435
|
}
|
|
436
|
+
function isButtonStyle(value) {
|
|
437
|
+
if (!value || typeof value !== "object") return false;
|
|
438
|
+
const v = value;
|
|
439
|
+
return BUTTON_FILL_TOKENS.includes(v.fill) && BUTTON_FILL_TOKENS.includes(v.textColor) && BUTTON_STYLES.includes(v.style) && BUTTON_RADII.includes(v.radius) && BUTTON_SIZES.includes(v.size);
|
|
440
|
+
}
|
|
320
441
|
function parseCustomFontWeight(raw) {
|
|
321
442
|
if (typeof raw !== "object" || raw === null) return null;
|
|
322
443
|
const w = raw;
|
|
@@ -336,6 +457,15 @@ function parseCustomFont(raw) {
|
|
|
336
457
|
if (weights.length === 0) return null;
|
|
337
458
|
return { family: f.family, label: f.label, weights };
|
|
338
459
|
}
|
|
460
|
+
var BUTTON_FIELDS = Object.keys(ROLES_BY_FIELD);
|
|
461
|
+
function parseTouchedButtons(raw) {
|
|
462
|
+
const out = {};
|
|
463
|
+
for (const variant of ["primary", "secondary"]) {
|
|
464
|
+
const list = raw?.[variant];
|
|
465
|
+
if (Array.isArray(list)) out[variant] = BUTTON_FIELDS.filter((f) => list.includes(f));
|
|
466
|
+
}
|
|
467
|
+
return out;
|
|
468
|
+
}
|
|
339
469
|
function parseBrandKit(raw) {
|
|
340
470
|
if (!raw) return null;
|
|
341
471
|
try {
|
|
@@ -345,11 +475,21 @@ function parseBrandKit(raw) {
|
|
|
345
475
|
const palette = p && typeof p.dark === "string" && typeof p.primary === "string" && typeof p.accent === "string" && typeof p.light === "string" ? { dark: p.dark, primary: p.primary, accent: p.accent, light: p.light } : void 0;
|
|
346
476
|
const fonts = f && typeof f.heading === "string" && typeof f.body === "string" ? { heading: f.heading, body: f.body } : void 0;
|
|
347
477
|
const customFonts = Array.isArray(parsed?.customFonts) ? parsed.customFonts.map(parseCustomFont).filter((c) => c !== null) : void 0;
|
|
348
|
-
|
|
478
|
+
const b = parsed?.buttons;
|
|
479
|
+
const buttons = b && isButtonStyle(b.primary) && isButtonStyle(b.secondary) ? { primary: b.primary, secondary: b.secondary } : void 0;
|
|
480
|
+
if (!palette && !fonts && !customFonts && !buttons) return null;
|
|
349
481
|
return {
|
|
350
482
|
...palette ? { palette } : {},
|
|
351
483
|
...fonts ? { fonts } : {},
|
|
352
|
-
...customFonts ? { customFonts } : {}
|
|
484
|
+
...customFonts ? { customFonts } : {},
|
|
485
|
+
...buttons ? { buttons } : {},
|
|
486
|
+
...parsed.touched && typeof parsed.touched === "object" ? {
|
|
487
|
+
touched: {
|
|
488
|
+
palette: parsed.touched.palette === true,
|
|
489
|
+
fonts: parsed.touched.fonts === true,
|
|
490
|
+
buttons: parseTouchedButtons(parsed.touched.buttons)
|
|
491
|
+
}
|
|
492
|
+
} : {}
|
|
353
493
|
};
|
|
354
494
|
} catch {
|
|
355
495
|
return null;
|
|
@@ -378,6 +518,39 @@ function loadBrandFonts(families) {
|
|
|
378
518
|
}
|
|
379
519
|
if (link.href !== href) link.href = href;
|
|
380
520
|
}
|
|
521
|
+
var BUTTON_RULES_STYLE_ID = "ohw-brand-button-rules";
|
|
522
|
+
function buttonRulesCss(kit) {
|
|
523
|
+
const rule = (variant) => {
|
|
524
|
+
const roles = touchedButtonRoles(variant, kit);
|
|
525
|
+
const v = (role) => `var(--brand-button-${variant}-${role})`;
|
|
526
|
+
const decls = [];
|
|
527
|
+
if (roles.has("bg")) decls.push(`background:${v("bg")} !important`);
|
|
528
|
+
if (roles.has("text")) decls.push(`color:${v("text")} !important`);
|
|
529
|
+
if (roles.has("border")) decls.push(`border:1.5px solid ${v("border")} !important`);
|
|
530
|
+
if (roles.has("radius")) decls.push(`border-radius:${v("radius")} !important`);
|
|
531
|
+
if (roles.has("padding-x")) decls.push(`padding:var(--brand-button-${variant}-padding, ${v("padding-y")} ${v("padding-x")}) !important`);
|
|
532
|
+
if (roles.has("font-size")) decls.push(`font-size:${v("font-size")} !important`);
|
|
533
|
+
if (decls.length === 0) return "";
|
|
534
|
+
const selectors = [`html .btn--${variant}`, `html .btn-${variant}`];
|
|
535
|
+
const labelRule = roles.has("text") ? `${selectors.map((x) => `${x} *`).join(",")}{color:inherit !important}` : "";
|
|
536
|
+
return `${selectors.join(",")}{${decls.join(";")}}` + labelRule + (roles.has("bg") ? `${selectors.map((x) => `${x}:hover`).join(",")}{opacity:0.88}` : "");
|
|
537
|
+
};
|
|
538
|
+
return rule("primary") + rule("secondary");
|
|
539
|
+
}
|
|
540
|
+
function syncButtonRules(kit) {
|
|
541
|
+
let el = document.getElementById(BUTTON_RULES_STYLE_ID);
|
|
542
|
+
const css = kit ? buttonRulesCss(kit) : "";
|
|
543
|
+
if (!css) {
|
|
544
|
+
el?.remove();
|
|
545
|
+
return;
|
|
546
|
+
}
|
|
547
|
+
if (!el) {
|
|
548
|
+
el = document.createElement("style");
|
|
549
|
+
el.id = BUTTON_RULES_STYLE_ID;
|
|
550
|
+
document.head.appendChild(el);
|
|
551
|
+
}
|
|
552
|
+
if (el.textContent !== css) el.textContent = css;
|
|
553
|
+
}
|
|
381
554
|
function escapeCssString(value) {
|
|
382
555
|
return value.replace(/\\/g, "\\\\").replace(/'/g, "\\'");
|
|
383
556
|
}
|
|
@@ -403,28 +576,47 @@ function loadCustomFonts(fonts) {
|
|
|
403
576
|
function applyBrandToDom(kit) {
|
|
404
577
|
const root = document.documentElement;
|
|
405
578
|
if (!kit) {
|
|
406
|
-
for (const name of [...BRAND_VAR_NAMES, ...LEGACY_BRAND_VAR_NAMES])
|
|
579
|
+
for (const name of [...BRAND_VAR_NAMES, ...LEGACY_BRAND_VAR_NAMES, ...BUTTON_VAR_NAMES]) {
|
|
580
|
+
root.style.removeProperty(name);
|
|
581
|
+
}
|
|
407
582
|
for (const name of [...FONT_VARS.heading, ...FONT_VARS.body]) root.style.removeProperty(name);
|
|
408
583
|
document.getElementById(BRAND_FONT_LINK_ID)?.remove();
|
|
409
584
|
document.getElementById(CUSTOM_FONT_STYLE_ID)?.remove();
|
|
585
|
+
syncButtonRules(null);
|
|
410
586
|
return;
|
|
411
587
|
}
|
|
588
|
+
const applyPalette = kit.touched ? kit.touched.palette === true : true;
|
|
589
|
+
const applyFonts = kit.touched ? kit.touched.fonts === true : true;
|
|
412
590
|
if (kit.palette) {
|
|
413
|
-
|
|
591
|
+
if (applyPalette) {
|
|
592
|
+
for (const [name, value] of Object.entries(brandColorVars(kit.palette))) root.style.setProperty(name, value);
|
|
593
|
+
} else {
|
|
594
|
+
for (const name of [...BRAND_VAR_NAMES, ...LEGACY_BRAND_VAR_NAMES]) root.style.removeProperty(name);
|
|
595
|
+
}
|
|
414
596
|
}
|
|
597
|
+
if (kit.buttons) {
|
|
598
|
+
for (const name of BUTTON_VAR_NAMES) root.style.removeProperty(name);
|
|
599
|
+
for (const [name, value] of Object.entries(buttonStyleVars({ ...kit, buttons: kit.buttons }))) root.style.setProperty(name, value);
|
|
600
|
+
}
|
|
601
|
+
syncButtonRules(kit.buttons ? kit : null);
|
|
415
602
|
if (kit.customFonts) {
|
|
416
603
|
loadCustomFonts(kit.customFonts);
|
|
417
604
|
}
|
|
418
605
|
if (kit.fonts) {
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
(
|
|
426
|
-
|
|
427
|
-
|
|
606
|
+
if (applyFonts) {
|
|
607
|
+
const heading = quoteFamily(kit.fonts.heading);
|
|
608
|
+
const body = quoteFamily(kit.fonts.body);
|
|
609
|
+
for (const name of FONT_VARS.heading) root.style.setProperty(name, heading);
|
|
610
|
+
for (const name of FONT_VARS.body) root.style.setProperty(name, body);
|
|
611
|
+
const customFamilies = new Set((kit.customFonts ?? []).map((f) => f.family));
|
|
612
|
+
const googleFamilies = [familyOf(kit.fonts.heading), familyOf(kit.fonts.body)].filter(
|
|
613
|
+
(f) => !customFamilies.has(f)
|
|
614
|
+
);
|
|
615
|
+
loadBrandFonts(googleFamilies);
|
|
616
|
+
} else {
|
|
617
|
+
for (const name of [...FONT_VARS.heading, ...FONT_VARS.body]) root.style.removeProperty(name);
|
|
618
|
+
document.getElementById(BRAND_FONT_LINK_ID)?.remove();
|
|
619
|
+
}
|
|
428
620
|
}
|
|
429
621
|
}
|
|
430
622
|
|
|
@@ -525,9 +717,9 @@ function styleSheetCss() {
|
|
|
525
717
|
);
|
|
526
718
|
}
|
|
527
719
|
const pad = { tight: 40, balanced: 64, airy: 96 };
|
|
528
|
-
for (const [spacing,
|
|
720
|
+
for (const [spacing, px2] of Object.entries(pad)) {
|
|
529
721
|
rules.push(
|
|
530
|
-
`[data-ohw-style-spacing="${spacing}"] { padding-top: ${
|
|
722
|
+
`[data-ohw-style-spacing="${spacing}"] { padding-top: ${px2}px !important; padding-bottom: ${px2}px !important; }`
|
|
531
723
|
);
|
|
532
724
|
}
|
|
533
725
|
rules.push(
|
|
@@ -574,7 +766,6 @@ var NODE_PROPS = [
|
|
|
574
766
|
"color",
|
|
575
767
|
"font-family",
|
|
576
768
|
"font-size",
|
|
577
|
-
"background",
|
|
578
769
|
"text-align",
|
|
579
770
|
"justify-content",
|
|
580
771
|
"align-items"
|
|
@@ -624,9 +815,6 @@ function clearNodeProps(root) {
|
|
|
624
815
|
h.removeAttribute(NODE_WROTE_ATTR);
|
|
625
816
|
}
|
|
626
817
|
}
|
|
627
|
-
function buttonSurfaceOf(el) {
|
|
628
|
-
return el.closest("a, button") ?? el;
|
|
629
|
-
}
|
|
630
818
|
function alignSubjectOf(el) {
|
|
631
819
|
const button = el.closest('[data-ohw-role="button"]');
|
|
632
820
|
if (button?.parentElement) return button.parentElement;
|
|
@@ -744,18 +932,6 @@ function applyStylesToDom(store) {
|
|
|
744
932
|
);
|
|
745
933
|
subject.setAttribute(NODE_WROTE_ATTR, "");
|
|
746
934
|
}
|
|
747
|
-
if (override.buttonBackground !== void 0 || override.buttonText !== void 0) {
|
|
748
|
-
const surface = buttonSurfaceOf(el);
|
|
749
|
-
if (override.buttonBackground !== void 0) {
|
|
750
|
-
saveInline(surface, "background");
|
|
751
|
-
surface.style.setProperty("background", override.buttonBackground, "important");
|
|
752
|
-
}
|
|
753
|
-
if (override.buttonText !== void 0) {
|
|
754
|
-
saveInline(surface, "color");
|
|
755
|
-
surface.style.setProperty("color", override.buttonText, "important");
|
|
756
|
-
}
|
|
757
|
-
surface.setAttribute(NODE_WROTE_ATTR, "");
|
|
758
|
-
}
|
|
759
935
|
}
|
|
760
936
|
}
|
|
761
937
|
for (const [sectionId, override] of Object.entries(store.sections)) {
|
|
@@ -1341,7 +1517,59 @@ var AI_MOBILE_CSS = [
|
|
|
1341
1517
|
"[data-ai-grid]{grid-template-columns:repeat(2, 1fr) !important}",
|
|
1342
1518
|
"}"
|
|
1343
1519
|
].join("");
|
|
1344
|
-
function
|
|
1520
|
+
function buttonSizeSpec(size) {
|
|
1521
|
+
switch (size) {
|
|
1522
|
+
case "s":
|
|
1523
|
+
return { padding: `${AI_TREE_TOKENS.spacing2}px ${AI_TREE_TOKENS.spacing4}px`, fontSize: 14 };
|
|
1524
|
+
case "l":
|
|
1525
|
+
return { padding: `${AI_TREE_TOKENS.spacing4}px ${AI_TREE_TOKENS.spacing8}px`, fontSize: 18 };
|
|
1526
|
+
case "m":
|
|
1527
|
+
default:
|
|
1528
|
+
return { padding: `${AI_TREE_TOKENS.spacing3}px ${AI_TREE_TOKENS.spacing6}px`, fontSize: AI_TREE_TOKENS.type.button.size };
|
|
1529
|
+
}
|
|
1530
|
+
}
|
|
1531
|
+
function buttonRadiusPx(radius) {
|
|
1532
|
+
switch (radius) {
|
|
1533
|
+
case "square":
|
|
1534
|
+
return 0;
|
|
1535
|
+
case "pill":
|
|
1536
|
+
return 999;
|
|
1537
|
+
case "rounded":
|
|
1538
|
+
default:
|
|
1539
|
+
return AI_TREE_TOKENS.radiusButton;
|
|
1540
|
+
}
|
|
1541
|
+
}
|
|
1542
|
+
function resolveButtonToken(brand, token) {
|
|
1543
|
+
return brand.palette[token];
|
|
1544
|
+
}
|
|
1545
|
+
function buttonColorStyle(ctx, variant) {
|
|
1546
|
+
const token = ctx.brand.buttons?.[variant];
|
|
1547
|
+
if (!token) return null;
|
|
1548
|
+
const fill = resolveButtonToken(ctx.brand, token.fill);
|
|
1549
|
+
const text = resolveButtonToken(ctx.brand, token.textColor);
|
|
1550
|
+
switch (token.style) {
|
|
1551
|
+
case "outline":
|
|
1552
|
+
return { background: "transparent", border: `1px solid ${fill}`, color: text };
|
|
1553
|
+
case "ghost":
|
|
1554
|
+
return { background: "transparent", border: "1px solid transparent", color: text };
|
|
1555
|
+
case "solid":
|
|
1556
|
+
default:
|
|
1557
|
+
return { background: fill, color: text };
|
|
1558
|
+
}
|
|
1559
|
+
}
|
|
1560
|
+
function buttonShellStyle(ctx, variant, fullWidth) {
|
|
1561
|
+
const buttonToken = ctx.brand.buttons?.[variant];
|
|
1562
|
+
if (buttonToken) {
|
|
1563
|
+
const { padding, fontSize } = buttonSizeSpec(buttonToken.size);
|
|
1564
|
+
return {
|
|
1565
|
+
borderRadius: buttonRadiusPx(buttonToken.radius),
|
|
1566
|
+
padding,
|
|
1567
|
+
fontFamily: ctx.brand.fonts.body,
|
|
1568
|
+
fontSize,
|
|
1569
|
+
lineHeight: AI_TREE_TOKENS.type.button.line,
|
|
1570
|
+
fontWeight: AI_TREE_TOKENS.type.button.weight
|
|
1571
|
+
};
|
|
1572
|
+
}
|
|
1345
1573
|
const bs = ctx.buttonStyle;
|
|
1346
1574
|
if (bs) {
|
|
1347
1575
|
return {
|
|
@@ -1451,6 +1679,22 @@ function pricingCardEmphasis(featured, ctx, hasBg) {
|
|
|
1451
1679
|
function textAttrs(ctx, path) {
|
|
1452
1680
|
return ctx.keyFor ? { "data-ohw-key": ctx.keyFor(path), "data-ohw-editable": "text" } : {};
|
|
1453
1681
|
}
|
|
1682
|
+
var AI_RESPONSIVE_CSS = [
|
|
1683
|
+
"@media (max-width: 960px) {",
|
|
1684
|
+
" [data-ai-responsive] [data-ai-grid] { grid-template-columns: repeat(2, 1fr) !important; }",
|
|
1685
|
+
' [data-ai-responsive] [data-ai-grid="1"] { grid-template-columns: 1fr !important; }',
|
|
1686
|
+
"}",
|
|
1687
|
+
"@media (max-width: 640px) {",
|
|
1688
|
+
" [data-ai-responsive] [data-ai-grid] { grid-template-columns: 1fr !important; }",
|
|
1689
|
+
" [data-ai-responsive] [data-ai-columns] > * { grid-column: 1 / -1 !important; }",
|
|
1690
|
+
// Group containers flatten to a column on phones; span placements come along for free.
|
|
1691
|
+
" [data-ai-responsive] [data-ai-group] { display: flex !important; flex-direction: column !important; }",
|
|
1692
|
+
" [data-ai-responsive] [data-ai-group] > * { grid-column: auto !important; }",
|
|
1693
|
+
" [data-ai-responsive] [data-ai-section-inner] { padding-left: 20px !important; padding-right: 20px !important; }",
|
|
1694
|
+
" [data-ai-responsive] { overflow-x: hidden; }",
|
|
1695
|
+
" [data-ai-responsive] img { max-width: 100%; }",
|
|
1696
|
+
"}"
|
|
1697
|
+
].join("\n");
|
|
1454
1698
|
var TRANSPARENT_PX = "data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7";
|
|
1455
1699
|
function MediaBox({
|
|
1456
1700
|
refValue,
|
|
@@ -1468,9 +1712,9 @@ function MediaBox({
|
|
|
1468
1712
|
const url = refValue ? ctx.resolveMedia(refValue) : null;
|
|
1469
1713
|
const isIcon = /^(lucide|simple):/.test(refValue);
|
|
1470
1714
|
const aspectRatio = aspect && /^\d+:\d+$/.test(aspect) ? aspect.replace(":", " / ") : void 0;
|
|
1471
|
-
const editAttrs = ctx.keyFor && editPath
|
|
1715
|
+
const editAttrs = ctx.keyFor && editPath ? {
|
|
1472
1716
|
"data-ohw-key": ctx.keyFor(editPath),
|
|
1473
|
-
...genericImageEdit ? { "data-ohw-editable": "image" } : {}
|
|
1717
|
+
...isIcon ? { "data-ohw-editable": "icon" } : genericImageEdit ? { "data-ohw-editable": "image" } : {}
|
|
1474
1718
|
} : {};
|
|
1475
1719
|
if (isIcon) {
|
|
1476
1720
|
const Icon = refValue.startsWith("lucide:") ? lucideByName(refValue.slice(7)) : null;
|
|
@@ -1478,6 +1722,7 @@ function MediaBox({
|
|
|
1478
1722
|
"span",
|
|
1479
1723
|
{
|
|
1480
1724
|
"data-ai-icon": refValue,
|
|
1725
|
+
...editAttrs,
|
|
1481
1726
|
style: {
|
|
1482
1727
|
display: "inline-flex",
|
|
1483
1728
|
width: 48,
|
|
@@ -1537,12 +1782,16 @@ function ButtonEl({
|
|
|
1537
1782
|
secondaryColor
|
|
1538
1783
|
}) {
|
|
1539
1784
|
const secondary = slots.variant === "secondary";
|
|
1785
|
+
const variant = secondary ? "secondary" : "primary";
|
|
1786
|
+
const tokenColorStyle = buttonColorStyle(ctx, variant);
|
|
1540
1787
|
const href = str(slots.href);
|
|
1541
1788
|
const linkAttrs = ctx.keyFor && path ? { "data-ohw-href-key": ctx.keyFor(`${path}.href`), "data-ohw-role": "button" } : {};
|
|
1542
1789
|
return /* @__PURE__ */ jsx(
|
|
1543
1790
|
"a",
|
|
1544
1791
|
{
|
|
1545
1792
|
href: href || void 0,
|
|
1793
|
+
className: `btn btn--${variant}`,
|
|
1794
|
+
"data-ohw-btn-variant": variant,
|
|
1546
1795
|
...linkAttrs,
|
|
1547
1796
|
style: {
|
|
1548
1797
|
display: fullWidth ? "flex" : "inline-flex",
|
|
@@ -1552,13 +1801,13 @@ function ButtonEl({
|
|
|
1552
1801
|
textDecoration: "none",
|
|
1553
1802
|
cursor: "pointer",
|
|
1554
1803
|
whiteSpace: "nowrap",
|
|
1555
|
-
...buttonShellStyle(ctx, fullWidth),
|
|
1556
|
-
...secondary ? { border: `1px solid ${secondaryColor ?? ctx.brand.palette.dark}`, color: secondaryColor ?? ctx.brand.palette.dark } : (
|
|
1804
|
+
...buttonShellStyle(ctx, variant, fullWidth),
|
|
1805
|
+
...tokenColorStyle ?? (secondary ? { border: `1px solid ${secondaryColor ?? ctx.brand.palette.dark}`, color: secondaryColor ?? ctx.brand.palette.dark } : (
|
|
1557
1806
|
// Off-band, prefer the template button's measured fill/label pair — a template may
|
|
1558
1807
|
// fill its CTAs with any token (hvac: accent bg, primary text). On an accent band
|
|
1559
1808
|
// the flipped palette keeps contrast, so the brand-driven colours stay.
|
|
1560
1809
|
!ctx.buttonLabel && ctx.buttonStyle?.background ? { background: ctx.buttonStyle.background, color: ctx.buttonStyle.color } : { background: ctx.brand.palette.primary, color: ctx.buttonLabel ?? primaryButtonLabel(ctx.brand) }
|
|
1561
|
-
)
|
|
1810
|
+
))
|
|
1562
1811
|
},
|
|
1563
1812
|
children: /* @__PURE__ */ jsx("span", { ...path ? textAttrs(ctx, `${path}.label`) : {}, children: str(slots.label) })
|
|
1564
1813
|
}
|
|
@@ -2532,7 +2781,7 @@ function CollectionBlock({ node, ctx, path }) {
|
|
|
2532
2781
|
return /* @__PURE__ */ jsx(
|
|
2533
2782
|
"div",
|
|
2534
2783
|
{
|
|
2535
|
-
"data-ai-grid":
|
|
2784
|
+
"data-ai-grid": String(itemsPerRow),
|
|
2536
2785
|
"data-ohw-pricing-collection": isPricing ? "" : void 0,
|
|
2537
2786
|
style: {
|
|
2538
2787
|
display: "grid",
|
|
@@ -2780,18 +3029,21 @@ function renderNode(node, ctx, path) {
|
|
|
2780
3029
|
"button",
|
|
2781
3030
|
{
|
|
2782
3031
|
type: "submit",
|
|
3032
|
+
className: "btn btn--primary",
|
|
3033
|
+
"data-ohw-btn-variant": "primary",
|
|
3034
|
+
"data-ohw-role": "button",
|
|
2783
3035
|
style: {
|
|
2784
3036
|
alignSelf: submitAlign,
|
|
2785
3037
|
border: "none",
|
|
2786
3038
|
cursor: "pointer",
|
|
2787
3039
|
// Shape/padding/typography follow the host template's own buttons.
|
|
2788
|
-
...buttonShellStyle(ctx),
|
|
3040
|
+
...buttonShellStyle(ctx, "primary"),
|
|
2789
3041
|
// Brand-styled: the template button's measured fill/label pair off-band, else
|
|
2790
3042
|
// primary fill with a brand-derived label so it reads on custom palettes.
|
|
2791
|
-
|
|
3043
|
+
...buttonColorStyle(ctx, "primary") ?? (!ctx.buttonLabel && ctx.buttonStyle?.background ? { background: ctx.buttonStyle.background, color: ctx.buttonStyle.color } : {
|
|
2792
3044
|
background: ctx.brand.palette.primary,
|
|
2793
3045
|
color: ctx.buttonLabel ?? primaryButtonLabel(ctx.brand)
|
|
2794
|
-
}
|
|
3046
|
+
})
|
|
2795
3047
|
},
|
|
2796
3048
|
children: /* @__PURE__ */ jsx("span", { ...textAttrs(ctx, `${path}.c${i}.label`), children: str(cs.label) })
|
|
2797
3049
|
},
|
|
@@ -2888,6 +3140,7 @@ function AiTreeRenderer({
|
|
|
2888
3140
|
{
|
|
2889
3141
|
"data-ai-section": tree.tag ?? "",
|
|
2890
3142
|
...bgAttrs,
|
|
3143
|
+
"data-ai-responsive": "",
|
|
2891
3144
|
style: {
|
|
2892
3145
|
position: "relative",
|
|
2893
3146
|
padding: `${pad}px 0`,
|
|
@@ -2898,12 +3151,13 @@ function AiTreeRenderer({
|
|
|
2898
3151
|
color: settings.sectionBackground === "accent" ? blockBrand.palette.dark : void 0
|
|
2899
3152
|
},
|
|
2900
3153
|
children: [
|
|
2901
|
-
|
|
3154
|
+
/* @__PURE__ */ jsx("style", { children: AI_RESPONSIVE_CSS }),
|
|
2902
3155
|
/* @__PURE__ */ jsx("style", { children: AI_MOBILE_CSS }),
|
|
3156
|
+
isOverlay && backgroundUrl && /* @__PURE__ */ jsx("div", { style: { position: "absolute", inset: 0, background: `rgba(255,255,255,${overlayAlpha})` } }),
|
|
2903
3157
|
/* @__PURE__ */ jsx(
|
|
2904
3158
|
"div",
|
|
2905
3159
|
{
|
|
2906
|
-
"data-ai-
|
|
3160
|
+
"data-ai-section-inner": "",
|
|
2907
3161
|
style: {
|
|
2908
3162
|
position: "relative",
|
|
2909
3163
|
maxWidth: AI_TREE_TOKENS.sectionMaxWidth,
|
|
@@ -2914,7 +3168,7 @@ function AiTreeRenderer({
|
|
|
2914
3168
|
children: tree.rows.map((row, r2) => /* @__PURE__ */ jsx(
|
|
2915
3169
|
"div",
|
|
2916
3170
|
{
|
|
2917
|
-
"data-ai-
|
|
3171
|
+
"data-ai-columns": "",
|
|
2918
3172
|
style: {
|
|
2919
3173
|
display: "grid",
|
|
2920
3174
|
gridTemplateColumns: "repeat(12, 1fr)",
|
|
@@ -3094,12 +3348,12 @@ function deriveTemplateButtonStyle() {
|
|
|
3094
3348
|
cs.borderBottomLeftRadius
|
|
3095
3349
|
].map((v) => v || "0px");
|
|
3096
3350
|
const radius = corners.every((v) => v === corners[0]) ? corners[0] : corners.join(" ");
|
|
3097
|
-
const
|
|
3098
|
-
const lineHeight =
|
|
3099
|
-
const contentH = btn.getBoundingClientRect().height -
|
|
3351
|
+
const px2 = (v) => parseFloat(v) || 0;
|
|
3352
|
+
const lineHeight = px2(cs.lineHeight) || px2(cs.fontSize) * 1.2;
|
|
3353
|
+
const contentH = btn.getBoundingClientRect().height - px2(cs.borderTopWidth) - px2(cs.borderBottomWidth);
|
|
3100
3354
|
const impliedY = Math.round(Math.max(0, (contentH - lineHeight) / 2));
|
|
3101
|
-
const padY = Math.max(
|
|
3102
|
-
const padX = Math.max(
|
|
3355
|
+
const padY = Math.max(px2(cs.paddingTop), px2(cs.paddingBottom), impliedY);
|
|
3356
|
+
const padX = Math.max(px2(cs.paddingLeft), px2(cs.paddingRight));
|
|
3103
3357
|
return {
|
|
3104
3358
|
radius: radius || "10px",
|
|
3105
3359
|
padding: `${padY}px ${padX}px`,
|
|
@@ -3318,9 +3572,10 @@ function applyAiSectionsToDom(state, options) {
|
|
|
3318
3572
|
if (existing && existing.serialized === serialized && existing.container.isConnected) {
|
|
3319
3573
|
continue;
|
|
3320
3574
|
}
|
|
3321
|
-
const isNewMount = !existing || !existing.container.isConnected;
|
|
3322
3575
|
let container = existing?.container;
|
|
3576
|
+
let isNewMount = false;
|
|
3323
3577
|
if (!container || !container.isConnected) {
|
|
3578
|
+
isNewMount = true;
|
|
3324
3579
|
existing?.root.unmount();
|
|
3325
3580
|
container?.remove();
|
|
3326
3581
|
container = document.createElement("div");
|
|
@@ -8016,6 +8271,14 @@ function ItemActionToolbar({
|
|
|
8016
8271
|
e.preventDefault();
|
|
8017
8272
|
e.stopPropagation();
|
|
8018
8273
|
onStyle?.();
|
|
8274
|
+
},
|
|
8275
|
+
// Same as Edit link: mousedown opens the panel and remounts this toolbar
|
|
8276
|
+
// (styleActive flips). Without stopping click, the gesture lands on whatever
|
|
8277
|
+
// is now under the cursor — navbar CTAs park the toolbar below the button, so
|
|
8278
|
+
// that miss deselects and the panel closes as soon as it opens.
|
|
8279
|
+
onClick: (e) => {
|
|
8280
|
+
e.preventDefault();
|
|
8281
|
+
e.stopPropagation();
|
|
8019
8282
|
}
|
|
8020
8283
|
},
|
|
8021
8284
|
children: /* @__PURE__ */ jsx11(Brush, { className: "size-4 shrink-0", "aria-hidden": true })
|
|
@@ -8338,20 +8601,32 @@ function ItemInteractionLayer({
|
|
|
8338
8601
|
itemDragSurface = true,
|
|
8339
8602
|
chromeGap,
|
|
8340
8603
|
toolbarAlign = "center",
|
|
8604
|
+
hidden = false,
|
|
8341
8605
|
className
|
|
8342
8606
|
}) {
|
|
8607
|
+
const localRef = useRef2(null);
|
|
8608
|
+
useLayoutEffect2(() => {
|
|
8609
|
+
const node = localRef.current;
|
|
8610
|
+
if (!node) return;
|
|
8611
|
+
node.style.display = hidden ? "none" : "block";
|
|
8612
|
+
}, [hidden, rect.top, rect.left, rect.width, rect.height, state]);
|
|
8343
8613
|
if (state === "default") return null;
|
|
8344
8614
|
const gap = chromeGap ?? (state === "hover" ? HOVER_CHROME_GAP : SELECTION_CHROME_GAP);
|
|
8345
8615
|
const isActive = state === "active-top" || state === "active-bottom";
|
|
8346
8616
|
const isDragging = state === "dragging";
|
|
8347
8617
|
const showToolbar = isActive && toolbar;
|
|
8348
8618
|
const showDragHandle = (isActive || isDragging) && showHandle;
|
|
8349
|
-
const itemDragEnabled = itemDragSurface && isActive &&
|
|
8619
|
+
const itemDragEnabled = itemDragSurface && isActive && !isDragging && !dragDisabled && Boolean(showHandle || onItemPointerDown);
|
|
8350
8620
|
const useDetachedBelowToolbar = Boolean(showToolbar && state === "active-bottom" && toolbarBelowRect);
|
|
8621
|
+
const setRootRef = (node) => {
|
|
8622
|
+
localRef.current = node;
|
|
8623
|
+
if (typeof elRef === "function") elRef(node);
|
|
8624
|
+
else if (elRef) elRef.current = node;
|
|
8625
|
+
};
|
|
8351
8626
|
return /* @__PURE__ */ jsxs5(
|
|
8352
8627
|
"div",
|
|
8353
8628
|
{
|
|
8354
|
-
ref:
|
|
8629
|
+
ref: setRootRef,
|
|
8355
8630
|
"data-ohw-item-interaction": "",
|
|
8356
8631
|
"data-ohw-item-interaction-state": state,
|
|
8357
8632
|
className: cn("pointer-events-none", className),
|
|
@@ -8361,7 +8636,8 @@ function ItemInteractionLayer({
|
|
|
8361
8636
|
left: rect.left - gap,
|
|
8362
8637
|
width: rect.width + gap * 2,
|
|
8363
8638
|
height: rect.height + gap * 2,
|
|
8364
|
-
zIndex: getChromeZIndex(state)
|
|
8639
|
+
zIndex: getChromeZIndex(state),
|
|
8640
|
+
display: hidden ? "none" : "block"
|
|
8365
8641
|
},
|
|
8366
8642
|
children: [
|
|
8367
8643
|
/* @__PURE__ */ jsx12(
|
|
@@ -9193,6 +9469,7 @@ function MediaOverlay({
|
|
|
9193
9469
|
(prev) => prev && prev.fullWidth === width && prev.height === height ? prev : { fullWidth: width, height }
|
|
9194
9470
|
);
|
|
9195
9471
|
}, [isVideo]);
|
|
9472
|
+
const replaceLabel = isVideo ? "Replace video" : hover.elementType === "bg-image" ? "Replace background" : "Replace image";
|
|
9196
9473
|
const replaceMode = buttonSize ? replaceButtonMode({ width: rect.width, height: rect.height }, buttonSize) : "none";
|
|
9197
9474
|
const box = {
|
|
9198
9475
|
position: "fixed",
|
|
@@ -9291,11 +9568,10 @@ function MediaOverlay({
|
|
|
9291
9568
|
className: "flex items-center justify-center cursor-pointer",
|
|
9292
9569
|
style: {
|
|
9293
9570
|
...box,
|
|
9294
|
-
//
|
|
9295
|
-
//
|
|
9296
|
-
//
|
|
9297
|
-
|
|
9298
|
-
pointerEvents: hover.hasTextOverlap || cueOnly ? "none" : "auto",
|
|
9571
|
+
// Visual only. `pointer-events: auto` on this full-bleed rect covered the navbar
|
|
9572
|
+
// (hero bg includes the absolute TopNav) and swallowed CTA press-drag. Text overlay
|
|
9573
|
+
// and cueOnly also need clicks to fall through — Replace / video controls opt back in.
|
|
9574
|
+
pointerEvents: "none",
|
|
9299
9575
|
// Selected: a firm component ring with no wash, so the image reads as chosen rather
|
|
9300
9576
|
// than hovered. Hover keeps the existing tinted preview.
|
|
9301
9577
|
boxShadow: selected ? "inset 0 0 0 2px var(--color-bridge-primary)" : "inset 0 0 0 1.5px var(--color-bridge-primary)",
|
|
@@ -9322,17 +9598,17 @@ function MediaOverlay({
|
|
|
9322
9598
|
},
|
|
9323
9599
|
children: [
|
|
9324
9600
|
isVideo ? /* @__PURE__ */ jsx15(Film, { size: 14 }) : /* @__PURE__ */ jsx15(ImageIcon, { size: 14 }),
|
|
9325
|
-
|
|
9601
|
+
replaceLabel
|
|
9326
9602
|
]
|
|
9327
9603
|
}
|
|
9328
9604
|
),
|
|
9329
|
-
replaceMode
|
|
9605
|
+
showChrome && replaceMode !== "none" && /* @__PURE__ */ jsxs7(
|
|
9330
9606
|
Button,
|
|
9331
9607
|
{
|
|
9332
9608
|
"data-ohw-media-overlay": "",
|
|
9333
9609
|
variant: "outline",
|
|
9334
9610
|
size: "sm",
|
|
9335
|
-
"aria-label":
|
|
9611
|
+
"aria-label": replaceLabel,
|
|
9336
9612
|
className: "gap-1.5 cursor-pointer hover:bg-background",
|
|
9337
9613
|
style: {
|
|
9338
9614
|
...OVERLAY_BUTTON_STYLE,
|
|
@@ -9355,7 +9631,7 @@ function MediaOverlay({
|
|
|
9355
9631
|
},
|
|
9356
9632
|
children: [
|
|
9357
9633
|
isVideo ? /* @__PURE__ */ jsx15(Film, { size: 14 }) : /* @__PURE__ */ jsx15(ImageIcon, { size: 14 }),
|
|
9358
|
-
replaceMode === "full" ?
|
|
9634
|
+
replaceMode === "full" ? replaceLabel : null
|
|
9359
9635
|
]
|
|
9360
9636
|
}
|
|
9361
9637
|
)
|
|
@@ -11182,6 +11458,13 @@ function findButtonAtPoint(x, y, media) {
|
|
|
11182
11458
|
if (hits.length === 0) return null;
|
|
11183
11459
|
return hits.reduce((best, el) => best.contains(el) ? el : best);
|
|
11184
11460
|
}
|
|
11461
|
+
function findNavbarCtaAtPoint(x, y) {
|
|
11462
|
+
const hits = Array.from(
|
|
11463
|
+
document.querySelectorAll('[data-ohw-role="navbar-button"]')
|
|
11464
|
+
).filter((el) => containsPoint(el, x, y) && !el.closest("[data-ohw-bridge]"));
|
|
11465
|
+
if (hits.length === 0) return null;
|
|
11466
|
+
return hits.reduce((best, el) => best.contains(el) ? el : best);
|
|
11467
|
+
}
|
|
11185
11468
|
|
|
11186
11469
|
// src/lib/session-search.ts
|
|
11187
11470
|
var STORAGE_KEY = "ohw-preserved-search";
|
|
@@ -11917,6 +12200,26 @@ import { useCallback as useCallback5, useEffect as useEffect8, useMemo as useMem
|
|
|
11917
12200
|
import { createPortal as createPortal2 } from "react-dom";
|
|
11918
12201
|
import { ArrowLeft as ArrowLeft2, Check as Check2 } from "lucide-react";
|
|
11919
12202
|
import { usePathname, useRouter as useRouter2 } from "next/navigation";
|
|
12203
|
+
|
|
12204
|
+
// src/lib/parent-scroll.ts
|
|
12205
|
+
function visibleBand(parentScroll) {
|
|
12206
|
+
const { iframeOffsetTop, headerH: visibleCanvasTop, canvasH } = parentScroll;
|
|
12207
|
+
const top = Math.max(0, visibleCanvasTop - iframeOffsetTop);
|
|
12208
|
+
const bottom = Math.min(window.innerHeight, visibleCanvasTop + canvasH - iframeOffsetTop);
|
|
12209
|
+
return { top, bottom: Math.max(top, bottom) };
|
|
12210
|
+
}
|
|
12211
|
+
function getIframeVisibleClip(parentScroll) {
|
|
12212
|
+
if (!parentScroll) return null;
|
|
12213
|
+
return visibleBand(parentScroll);
|
|
12214
|
+
}
|
|
12215
|
+
function getIframeChromeClip(parentScroll) {
|
|
12216
|
+
if (!parentScroll) return null;
|
|
12217
|
+
const band = visibleBand(parentScroll);
|
|
12218
|
+
const promptBarH = Math.max(0, parentScroll.promptBarH ?? 0);
|
|
12219
|
+
return { top: band.top, bottom: Math.max(band.top, band.bottom - promptBarH) };
|
|
12220
|
+
}
|
|
12221
|
+
|
|
12222
|
+
// src/ui/link-modal/SectionPickerOverlay.tsx
|
|
11920
12223
|
import { jsx as jsx27, jsxs as jsxs17 } from "react/jsx-runtime";
|
|
11921
12224
|
var DIM_OVERLAY = "rgba(0, 0, 0, 0.45)";
|
|
11922
12225
|
function rectsEqual(a, b) {
|
|
@@ -12054,20 +12357,22 @@ function SectionPickerOverlay({
|
|
|
12054
12357
|
[]
|
|
12055
12358
|
);
|
|
12056
12359
|
useEffect8(() => {
|
|
12057
|
-
const applyClip = (iframeOffsetTop, visibleCanvasTop, canvasH) => {
|
|
12058
|
-
const
|
|
12059
|
-
|
|
12060
|
-
|
|
12061
|
-
|
|
12062
|
-
|
|
12360
|
+
const applyClip = (iframeOffsetTop, visibleCanvasTop, canvasH, promptBarH = 0) => {
|
|
12361
|
+
const next = getIframeVisibleClip({
|
|
12362
|
+
iframeOffsetTop,
|
|
12363
|
+
headerH: visibleCanvasTop,
|
|
12364
|
+
canvasH,
|
|
12365
|
+
promptBarH
|
|
12366
|
+
});
|
|
12367
|
+
if (!next) return;
|
|
12063
12368
|
setChromeClip(
|
|
12064
|
-
(prev) => prev.top === top && prev.bottom === bottom ? prev :
|
|
12369
|
+
(prev) => prev.top === next.top && prev.bottom === next.bottom ? prev : next
|
|
12065
12370
|
);
|
|
12066
12371
|
};
|
|
12067
12372
|
const onParentScroll = (e) => {
|
|
12068
12373
|
if (e.data?.type !== "ow:parent-scroll") return;
|
|
12069
|
-
const { iframeOffsetTop, headerH, canvasH } = e.data;
|
|
12070
|
-
applyClip(iframeOffsetTop, headerH, canvasH);
|
|
12374
|
+
const { iframeOffsetTop, headerH, canvasH, promptBarH = 0 } = e.data;
|
|
12375
|
+
applyClip(iframeOffsetTop, headerH, canvasH, promptBarH);
|
|
12071
12376
|
iframeOffsetTopRef.current = iframeOffsetTop;
|
|
12072
12377
|
if (!pointerScreenRef.current && pointerRef.current) {
|
|
12073
12378
|
pointerScreenRef.current = {
|
|
@@ -15660,6 +15965,7 @@ function readLogoSizeState(content, placement) {
|
|
|
15660
15965
|
function getLogoElement(el) {
|
|
15661
15966
|
const marked = el.closest('[data-ohw-role="logo"], [data-ohw-logo]');
|
|
15662
15967
|
if (marked) return marked;
|
|
15968
|
+
if (el.closest('[data-ohw-editable="icon"]')) return null;
|
|
15663
15969
|
const root = el.closest("nav, [data-ohw-nav-root], footer");
|
|
15664
15970
|
if (!root) return null;
|
|
15665
15971
|
const anchor = el.closest("a");
|
|
@@ -15737,36 +16043,50 @@ import { X as X5 } from "lucide-react";
|
|
|
15737
16043
|
import { jsx as jsx29, jsxs as jsxs19 } from "react/jsx-runtime";
|
|
15738
16044
|
var PANEL_WIDTH = 256;
|
|
15739
16045
|
var EDGE_MARGIN = 16;
|
|
16046
|
+
var HEADER_MIN = 56;
|
|
15740
16047
|
function getVisibleClip(parentScroll) {
|
|
15741
16048
|
const left = 0;
|
|
15742
16049
|
const right = window.innerWidth;
|
|
15743
|
-
|
|
16050
|
+
const band = getIframeChromeClip(parentScroll);
|
|
16051
|
+
if (!band) {
|
|
15744
16052
|
return { top: 0, bottom: window.innerHeight, left, right };
|
|
15745
16053
|
}
|
|
15746
|
-
|
|
15747
|
-
const top = Math.max(0, visibleCanvasTop - iframeOffsetTop);
|
|
15748
|
-
const bottom = Math.min(window.innerHeight, visibleCanvasTop + canvasH - iframeOffsetTop);
|
|
15749
|
-
return { top, bottom: Math.max(top, bottom), left, right };
|
|
16054
|
+
return { ...band, left, right };
|
|
15750
16055
|
}
|
|
15751
|
-
function defaultFloatingPanelPosition(parentScroll,
|
|
16056
|
+
function defaultFloatingPanelPosition(parentScroll, _panelHeight = 280) {
|
|
15752
16057
|
const clip = getVisibleClip(parentScroll);
|
|
15753
16058
|
return {
|
|
15754
16059
|
x: Math.max(EDGE_MARGIN, clip.right - PANEL_WIDTH - EDGE_MARGIN),
|
|
15755
|
-
y:
|
|
15756
|
-
Math.max(clip.top + EDGE_MARGIN, EDGE_MARGIN),
|
|
15757
|
-
Math.max(clip.top + EDGE_MARGIN, clip.bottom - panelHeight - EDGE_MARGIN)
|
|
15758
|
-
)
|
|
16060
|
+
y: clip.top + EDGE_MARGIN
|
|
15759
16061
|
};
|
|
15760
16062
|
}
|
|
15761
|
-
function
|
|
16063
|
+
function clampX(x, panelW) {
|
|
16064
|
+
const left = EDGE_MARGIN;
|
|
16065
|
+
const maxX = Math.max(left, window.innerWidth - panelW - EDGE_MARGIN);
|
|
16066
|
+
return Math.min(Math.max(x, left), maxX);
|
|
16067
|
+
}
|
|
16068
|
+
function clampDragPosition(pos, parentScroll, panelW) {
|
|
15762
16069
|
const clip = getVisibleClip(parentScroll);
|
|
15763
|
-
const
|
|
15764
|
-
const maxY = Math.max(
|
|
16070
|
+
const minY = clip.top + EDGE_MARGIN;
|
|
16071
|
+
const maxY = Math.max(minY, clip.bottom - EDGE_MARGIN - HEADER_MIN);
|
|
15765
16072
|
return {
|
|
15766
|
-
x:
|
|
15767
|
-
y: Math.min(Math.max(pos.y,
|
|
16073
|
+
x: clampX(pos.x, panelW),
|
|
16074
|
+
y: Math.min(Math.max(pos.y, minY), maxY)
|
|
15768
16075
|
};
|
|
15769
16076
|
}
|
|
16077
|
+
function fitPanelInClip(homeY, parentScroll, preferredHeight) {
|
|
16078
|
+
const clip = getVisibleClip(parentScroll);
|
|
16079
|
+
const minY = clip.top + EDGE_MARGIN;
|
|
16080
|
+
const maxBottom = clip.bottom - EDGE_MARGIN;
|
|
16081
|
+
const band = Math.max(HEADER_MIN, maxBottom - minY);
|
|
16082
|
+
let y = Math.max(homeY, minY);
|
|
16083
|
+
const want = Math.min(Math.max(preferredHeight, HEADER_MIN), band);
|
|
16084
|
+
if (y + want > maxBottom) {
|
|
16085
|
+
y = Math.max(minY, maxBottom - want);
|
|
16086
|
+
}
|
|
16087
|
+
const maxHeight = Math.max(HEADER_MIN, Math.floor(maxBottom - y));
|
|
16088
|
+
return { y, maxHeight };
|
|
16089
|
+
}
|
|
15770
16090
|
function FloatingPanel({
|
|
15771
16091
|
open,
|
|
15772
16092
|
title,
|
|
@@ -15783,19 +16103,54 @@ function FloatingPanel({
|
|
|
15783
16103
|
const panelRef = useRef9(null);
|
|
15784
16104
|
const [measured, setMeasured] = useState12({ w: PANEL_WIDTH, h: 280 });
|
|
15785
16105
|
const dragRef = useRef9(null);
|
|
15786
|
-
const
|
|
15787
|
-
|
|
16106
|
+
const homeRef = useRef9(null);
|
|
16107
|
+
if (!open) {
|
|
16108
|
+
homeRef.current = null;
|
|
16109
|
+
} else if (position) {
|
|
16110
|
+
homeRef.current = position;
|
|
16111
|
+
} else if (homeRef.current == null) {
|
|
16112
|
+
homeRef.current = defaultFloatingPanelPosition(parentScroll);
|
|
16113
|
+
}
|
|
16114
|
+
const [liveScroll, setLiveScroll] = useState12(parentScroll);
|
|
16115
|
+
const home = position ?? homeRef.current ?? defaultFloatingPanelPosition(parentScroll);
|
|
16116
|
+
const { y: fittedY, maxHeight } = fitPanelInClip(home.y, liveScroll, measured.h);
|
|
16117
|
+
const clamped = {
|
|
16118
|
+
x: clampX(home.x, measured.w),
|
|
16119
|
+
y: fittedY
|
|
16120
|
+
};
|
|
16121
|
+
useEffect11(() => {
|
|
16122
|
+
setLiveScroll(parentScroll);
|
|
16123
|
+
}, [parentScroll]);
|
|
16124
|
+
useEffect11(() => {
|
|
16125
|
+
if (!open) return;
|
|
16126
|
+
const onParentScroll = (e) => {
|
|
16127
|
+
if (e.data?.type !== "ow:parent-scroll") return;
|
|
16128
|
+
const { iframeOffsetTop, headerH, canvasH, promptBarH = 0 } = e.data;
|
|
16129
|
+
setLiveScroll({ iframeOffsetTop, headerH, canvasH, promptBarH });
|
|
16130
|
+
};
|
|
16131
|
+
window.addEventListener("message", onParentScroll);
|
|
16132
|
+
return () => window.removeEventListener("message", onParentScroll);
|
|
16133
|
+
}, [open]);
|
|
16134
|
+
const positionRef = useRef9(position);
|
|
16135
|
+
useLayoutEffect4(() => {
|
|
16136
|
+
if (!open) {
|
|
16137
|
+
positionRef.current = position;
|
|
16138
|
+
return;
|
|
16139
|
+
}
|
|
16140
|
+
if (position == null && positionRef.current != null) {
|
|
16141
|
+
homeRef.current = defaultFloatingPanelPosition(liveScroll ?? parentScroll);
|
|
16142
|
+
}
|
|
16143
|
+
positionRef.current = position;
|
|
16144
|
+
}, [open, position, liveScroll, parentScroll]);
|
|
15788
16145
|
useLayoutEffect4(() => {
|
|
15789
16146
|
if (!open || !panelRef.current) return;
|
|
15790
16147
|
const el = panelRef.current;
|
|
15791
|
-
const
|
|
16148
|
+
const header = el.querySelector("[data-ohw-floating-panel-header]");
|
|
16149
|
+
const body = el.querySelector("[data-ohw-floating-panel-body]");
|
|
16150
|
+
const contentH = (header?.offsetHeight ?? 0) + (body?.scrollHeight ?? 0) || el.scrollHeight || 280;
|
|
16151
|
+
const next = { w: el.offsetWidth || PANEL_WIDTH, h: contentH };
|
|
15792
16152
|
setMeasured((prev) => prev.w === next.w && prev.h === next.h ? prev : next);
|
|
15793
16153
|
}, [open, children, title, context]);
|
|
15794
|
-
useEffect11(() => {
|
|
15795
|
-
if (!open || !position || !onPositionChange) return;
|
|
15796
|
-
const next = clampPosition(position, parentScroll, measured.w, measured.h);
|
|
15797
|
-
if (next.x !== position.x || next.y !== position.y) onPositionChange(next);
|
|
15798
|
-
}, [open, parentScroll, measured.w, measured.h, position, onPositionChange]);
|
|
15799
16154
|
const onHeaderPointerDown = useCallback7(
|
|
15800
16155
|
(e) => {
|
|
15801
16156
|
if (e.button !== 0) return;
|
|
@@ -15829,18 +16184,17 @@ function FloatingPanel({
|
|
|
15829
16184
|
return;
|
|
15830
16185
|
}
|
|
15831
16186
|
e.preventDefault();
|
|
15832
|
-
const next =
|
|
16187
|
+
const next = clampDragPosition(
|
|
15833
16188
|
{
|
|
15834
16189
|
x: drag.originX + (e.clientX - drag.startX),
|
|
15835
16190
|
y: drag.originY + (e.clientY - drag.startY)
|
|
15836
16191
|
},
|
|
15837
|
-
|
|
15838
|
-
measured.w
|
|
15839
|
-
measured.h
|
|
16192
|
+
liveScroll,
|
|
16193
|
+
measured.w
|
|
15840
16194
|
);
|
|
15841
16195
|
onPositionChange?.(next);
|
|
15842
16196
|
},
|
|
15843
|
-
[measured.
|
|
16197
|
+
[measured.w, onPositionChange, liveScroll]
|
|
15844
16198
|
);
|
|
15845
16199
|
const endDrag = useCallback7((e) => {
|
|
15846
16200
|
const drag = dragRef.current;
|
|
@@ -15870,7 +16224,7 @@ function FloatingPanel({
|
|
|
15870
16224
|
"fixed z-[2147483647] flex w-64 flex-col overflow-hidden rounded-xl border border-border bg-background font-sans shadow-lg outline-none",
|
|
15871
16225
|
className
|
|
15872
16226
|
),
|
|
15873
|
-
style: { left: clamped.x, top: clamped.y },
|
|
16227
|
+
style: { left: clamped.x, top: clamped.y, maxHeight },
|
|
15874
16228
|
onMouseDown: (e) => e.stopPropagation(),
|
|
15875
16229
|
onPointerDown: (e) => e.stopPropagation(),
|
|
15876
16230
|
onClick: (e) => e.stopPropagation(),
|
|
@@ -15879,7 +16233,7 @@ function FloatingPanel({
|
|
|
15879
16233
|
"div",
|
|
15880
16234
|
{
|
|
15881
16235
|
"data-ohw-floating-panel-header": "",
|
|
15882
|
-
className: "relative flex cursor-grab items-start gap-2 border-b border-border py-
|
|
16236
|
+
className: "relative flex shrink-0 cursor-grab items-start gap-2 border-b border-border py-4! pl-5! pr-11! active:cursor-grabbing",
|
|
15883
16237
|
onPointerDown: onHeaderPointerDown,
|
|
15884
16238
|
onPointerMove: onHeaderPointerMove,
|
|
15885
16239
|
onPointerUp: endDrag,
|
|
@@ -15914,7 +16268,11 @@ function FloatingPanel({
|
|
|
15914
16268
|
"div",
|
|
15915
16269
|
{
|
|
15916
16270
|
"data-ohw-floating-panel-body": "",
|
|
15917
|
-
className: cn(
|
|
16271
|
+
className: cn(
|
|
16272
|
+
"flex min-h-0 w-full flex-1 flex-col gap-4 overflow-y-auto overscroll-contain p-4",
|
|
16273
|
+
bodyClassName
|
|
16274
|
+
),
|
|
16275
|
+
style: { WebkitOverflowScrolling: "touch" },
|
|
15918
16276
|
children
|
|
15919
16277
|
}
|
|
15920
16278
|
)
|
|
@@ -15992,122 +16350,1556 @@ function SocialsDisplayPanel({ display, onChange, className }) {
|
|
|
15992
16350
|
] });
|
|
15993
16351
|
}
|
|
15994
16352
|
|
|
15995
|
-
// src/
|
|
15996
|
-
|
|
15997
|
-
|
|
15998
|
-
|
|
15999
|
-
|
|
16353
|
+
// src/ui/button-style-panel.tsx
|
|
16354
|
+
import { Check as Check3 } from "lucide-react";
|
|
16355
|
+
|
|
16356
|
+
// src/lib/button-styles.ts
|
|
16357
|
+
var BUTTON_VARIANTS_KEY = "__ohw_button_variants";
|
|
16358
|
+
var BUTTON_SIZES_KEY = "__ohw_button_sizes";
|
|
16359
|
+
var BUTTON_ASSIGNMENTS_KEY = "__ohw_button_assignments";
|
|
16360
|
+
var BUTTON_VARIANT_IDS = ["primary", "secondary", "ghost"];
|
|
16361
|
+
var BUTTON_SIZE_IDS = ["s", "m", "l"];
|
|
16362
|
+
var TRANSPARENT = "rgba(0, 0, 0, 0)";
|
|
16363
|
+
var REFERENCE_SIZES = {
|
|
16364
|
+
s: { height: 40, paddingTop: 8, paddingRight: 16, paddingBottom: 8, paddingLeft: 16, fontSize: 15, borderRadius: 8, gap: 8 },
|
|
16365
|
+
m: { height: 48, paddingTop: 12, paddingRight: 24, paddingBottom: 12, paddingLeft: 24, fontSize: 15, borderRadius: 8, gap: 8 },
|
|
16366
|
+
l: { height: 56, paddingTop: 16, paddingRight: 32, paddingBottom: 16, paddingLeft: 32, fontSize: 15, borderRadius: 8, gap: 8 }
|
|
16367
|
+
};
|
|
16368
|
+
function buttonStyleContext(_el) {
|
|
16369
|
+
return "Button";
|
|
16370
|
+
}
|
|
16371
|
+
function previewSlotBackground(el) {
|
|
16372
|
+
let node = el.parentElement;
|
|
16373
|
+
while (node && node !== el.ownerDocument.documentElement) {
|
|
16374
|
+
if (node.closest("[data-ohw-bridge], [data-ohw-bridge-root]")) {
|
|
16375
|
+
node = node.parentElement;
|
|
16376
|
+
continue;
|
|
16377
|
+
}
|
|
16378
|
+
const bg = getComputedStyle(node).backgroundColor;
|
|
16379
|
+
const parsed = parseColor(bg);
|
|
16380
|
+
if (parsed && !isTransparent(parsed)) return bg;
|
|
16381
|
+
node = node.parentElement;
|
|
16000
16382
|
}
|
|
16383
|
+
const root = el.ownerDocument.documentElement;
|
|
16384
|
+
const style = getComputedStyle(root);
|
|
16385
|
+
for (const name of ["--brand-surface", "--brand-background", "--ohw-brand-light", "--color-light"]) {
|
|
16386
|
+
const value = style.getPropertyValue(name).trim();
|
|
16387
|
+
if (value) return value;
|
|
16388
|
+
}
|
|
16389
|
+
return "var(--brand-background, var(--ohw-brand-light, var(--color-light, #ffffff)))";
|
|
16001
16390
|
}
|
|
16002
|
-
function
|
|
16003
|
-
|
|
16004
|
-
|
|
16391
|
+
function buttonId(el) {
|
|
16392
|
+
if (!el) return null;
|
|
16393
|
+
const button = el.matches(CTA_BUTTON_SELECTOR) ? el : el.closest(CTA_BUTTON_SELECTOR);
|
|
16394
|
+
const id = button?.getAttribute("data-ohw-href-key")?.trim();
|
|
16395
|
+
return id || null;
|
|
16005
16396
|
}
|
|
16006
|
-
function
|
|
16007
|
-
|
|
16397
|
+
function isButtonVariantId(value) {
|
|
16398
|
+
return BUTTON_VARIANT_IDS.includes(value);
|
|
16008
16399
|
}
|
|
16009
|
-
function
|
|
16010
|
-
|
|
16011
|
-
document.documentElement.setAttribute("data-ohw-item-dragging", "");
|
|
16012
|
-
clearTextSelection();
|
|
16400
|
+
function isButtonSizeId(value) {
|
|
16401
|
+
return BUTTON_SIZE_IDS.includes(value);
|
|
16013
16402
|
}
|
|
16014
|
-
function
|
|
16015
|
-
const
|
|
16016
|
-
|
|
16017
|
-
document.documentElement.removeAttribute("data-ohw-item-dragging");
|
|
16018
|
-
if (wasDragging) clearTextSelection();
|
|
16403
|
+
function px(value) {
|
|
16404
|
+
const rounded = Math.round(value * 100) / 100;
|
|
16405
|
+
return `${rounded}px`;
|
|
16019
16406
|
}
|
|
16020
|
-
|
|
16021
|
-
|
|
16022
|
-
|
|
16023
|
-
|
|
16024
|
-
|
|
16025
|
-
|
|
16026
|
-
return listActiveNavbarItems(draggedEl).filter((el) => {
|
|
16027
|
-
const key = el.getAttribute("data-ohw-href-key");
|
|
16028
|
-
return isNavbarHrefKey(key) && !isNestedNavChild(el);
|
|
16029
|
-
});
|
|
16407
|
+
function parsePx(value, rootFont = 16) {
|
|
16408
|
+
if (!value) return 0;
|
|
16409
|
+
const n = parseFloat(value);
|
|
16410
|
+
if (!Number.isFinite(n)) return 0;
|
|
16411
|
+
if (value.trim().endsWith("rem") || value.trim().endsWith("em")) return n * rootFont;
|
|
16412
|
+
return n;
|
|
16030
16413
|
}
|
|
16031
|
-
function
|
|
16032
|
-
|
|
16033
|
-
|
|
16034
|
-
|
|
16035
|
-
const trigger = group.querySelector(":scope > [data-ohw-href-key]") ?? Array.from(group.querySelectorAll("[data-ohw-href-key]")).find(
|
|
16036
|
-
(el) => !el.closest("[data-ohw-nav-children]")
|
|
16037
|
-
) ?? null;
|
|
16038
|
-
const key = trigger?.getAttribute("data-ohw-href-key");
|
|
16039
|
-
return key && isNavbarHrefKey(key) ? key : null;
|
|
16414
|
+
function classifyHeight(height) {
|
|
16415
|
+
if (height < 44) return "s";
|
|
16416
|
+
if (height < 52) return "m";
|
|
16417
|
+
return "l";
|
|
16040
16418
|
}
|
|
16041
|
-
function
|
|
16042
|
-
|
|
16043
|
-
|
|
16044
|
-
|
|
16045
|
-
|
|
16046
|
-
|
|
16047
|
-
|
|
16048
|
-
|
|
16049
|
-
(
|
|
16050
|
-
|
|
16419
|
+
function scaleGeometry(geometry, scale = 0.75) {
|
|
16420
|
+
return {
|
|
16421
|
+
paddingTop: px(parsePx(geometry.paddingTop) * scale),
|
|
16422
|
+
paddingRight: px(parsePx(geometry.paddingRight) * scale),
|
|
16423
|
+
paddingBottom: px(parsePx(geometry.paddingBottom) * scale),
|
|
16424
|
+
paddingLeft: px(parsePx(geometry.paddingLeft) * scale),
|
|
16425
|
+
fontSize: px(parsePx(geometry.fontSize) * scale),
|
|
16426
|
+
borderRadius: px(parsePx(geometry.borderRadius) * scale),
|
|
16427
|
+
gap: px(parsePx(geometry.gap) * scale),
|
|
16428
|
+
height: Math.round(geometry.height * scale)
|
|
16429
|
+
};
|
|
16051
16430
|
}
|
|
16052
|
-
function
|
|
16053
|
-
const
|
|
16054
|
-
|
|
16055
|
-
|
|
16056
|
-
|
|
16057
|
-
|
|
16058
|
-
|
|
16059
|
-
|
|
16431
|
+
function relativeLuminance(color) {
|
|
16432
|
+
const channel = (value) => {
|
|
16433
|
+
const s = value / 255;
|
|
16434
|
+
return s <= 0.03928 ? s / 12.92 : ((s + 0.055) / 1.055) ** 2.4;
|
|
16435
|
+
};
|
|
16436
|
+
return 0.2126 * channel(color.r) + 0.7152 * channel(color.g) + 0.0722 * channel(color.b);
|
|
16437
|
+
}
|
|
16438
|
+
function contrastRatio(a, b) {
|
|
16439
|
+
const lighter = Math.max(relativeLuminance(a), relativeLuminance(b));
|
|
16440
|
+
const darker = Math.min(relativeLuminance(a), relativeLuminance(b));
|
|
16441
|
+
return (lighter + 0.05) / (darker + 0.05);
|
|
16442
|
+
}
|
|
16443
|
+
function compositeOver(fg, bg) {
|
|
16444
|
+
const a = fg.a + bg.a * (1 - fg.a);
|
|
16445
|
+
if (a < 1e-3) return { ...bg, a: 0 };
|
|
16446
|
+
return {
|
|
16447
|
+
r: (fg.r * fg.a + bg.r * bg.a * (1 - fg.a)) / a,
|
|
16448
|
+
g: (fg.g * fg.a + bg.g * bg.a * (1 - fg.a)) / a,
|
|
16449
|
+
b: (fg.b * fg.a + bg.b * bg.a * (1 - fg.a)) / a,
|
|
16450
|
+
a
|
|
16451
|
+
};
|
|
16452
|
+
}
|
|
16453
|
+
function previewSlotForChrome(chrome, slotBackground) {
|
|
16454
|
+
const text = parseColor(chrome.color);
|
|
16455
|
+
if (!text || text.a < 0.2) return slotBackground;
|
|
16456
|
+
const slot = parseColor(slotBackground) ?? { r: 250, g: 250, b: 249, a: 1 };
|
|
16457
|
+
const fill = parseColor(chrome.background);
|
|
16458
|
+
const effective = fill && !isTransparent(fill) ? compositeOver(fill, slot) : slot;
|
|
16459
|
+
if (contrastRatio(text, effective) >= 3) return slotBackground;
|
|
16460
|
+
return relativeLuminance(text) > 0.55 ? "#2c2c2c" : "#f4f4f5";
|
|
16461
|
+
}
|
|
16462
|
+
function parseColor(input) {
|
|
16463
|
+
if (!input) return null;
|
|
16464
|
+
const value = input.trim().toLowerCase();
|
|
16465
|
+
if (value === "transparent") return { r: 0, g: 0, b: 0, a: 0 };
|
|
16466
|
+
const hex = value.match(/^#([0-9a-f]{3,8})$/);
|
|
16467
|
+
if (hex) {
|
|
16468
|
+
const raw = hex[1];
|
|
16469
|
+
const expand = (pair) => parseInt(pair.length === 1 ? pair + pair : pair, 16);
|
|
16470
|
+
if (raw.length === 3 || raw.length === 4) {
|
|
16471
|
+
return {
|
|
16472
|
+
r: expand(raw[0]),
|
|
16473
|
+
g: expand(raw[1]),
|
|
16474
|
+
b: expand(raw[2]),
|
|
16475
|
+
a: raw.length === 4 ? expand(raw[3]) / 255 : 1
|
|
16476
|
+
};
|
|
16477
|
+
}
|
|
16478
|
+
if (raw.length === 6 || raw.length === 8) {
|
|
16479
|
+
return {
|
|
16480
|
+
r: expand(raw.slice(0, 2)),
|
|
16481
|
+
g: expand(raw.slice(2, 4)),
|
|
16482
|
+
b: expand(raw.slice(4, 6)),
|
|
16483
|
+
a: raw.length === 8 ? expand(raw.slice(6, 8)) / 255 : 1
|
|
16484
|
+
};
|
|
16485
|
+
}
|
|
16060
16486
|
}
|
|
16061
|
-
const
|
|
16062
|
-
|
|
16063
|
-
|
|
16064
|
-
|
|
16487
|
+
const rgb = value.match(
|
|
16488
|
+
/^rgba?\(\s*([\d.]+)[%\s,]+([\d.]+)[%\s,]+([\d.]+)(?:%?\s*[,/]\s*([\d.]+%?))?\s*\)$/
|
|
16489
|
+
);
|
|
16490
|
+
if (rgb) {
|
|
16491
|
+
const alphaRaw = rgb[4];
|
|
16492
|
+
const alpha = alphaRaw == null ? 1 : alphaRaw.endsWith("%") ? parseFloat(alphaRaw) / 100 : parseFloat(alphaRaw);
|
|
16493
|
+
return { r: Number(rgb[1]), g: Number(rgb[2]), b: Number(rgb[3]), a: alpha };
|
|
16494
|
+
}
|
|
16495
|
+
const oklch = value.match(
|
|
16496
|
+
/^oklch\(\s*([\d.]+%?)\s+([\d.]+)\s+([\d.]+)(?:deg)?(?:\s*\/\s*([\d.]+%?))?\s*\)$/
|
|
16497
|
+
);
|
|
16498
|
+
if (oklch) {
|
|
16499
|
+
const Lraw = oklch[1];
|
|
16500
|
+
const L = Lraw.endsWith("%") ? parseFloat(Lraw) / 100 : parseFloat(Lraw);
|
|
16501
|
+
const gray = Math.max(0, Math.min(1, L)) * 255;
|
|
16502
|
+
const alphaRaw = oklch[4];
|
|
16503
|
+
const alpha = alphaRaw == null ? 1 : alphaRaw.endsWith("%") ? parseFloat(alphaRaw) / 100 : parseFloat(alphaRaw);
|
|
16504
|
+
return { r: gray, g: gray, b: gray, a: alpha };
|
|
16505
|
+
}
|
|
16506
|
+
return null;
|
|
16065
16507
|
}
|
|
16066
|
-
function
|
|
16067
|
-
|
|
16068
|
-
|
|
16069
|
-
|
|
16070
|
-
|
|
16071
|
-
|
|
16072
|
-
|
|
16073
|
-
|
|
16074
|
-
insertIndex: 0,
|
|
16075
|
-
parentId: null,
|
|
16076
|
-
left: rect.left,
|
|
16077
|
-
top: rect.top + rect.height / 2 - barThickness / 2,
|
|
16078
|
-
width: Math.max(rect.width, 40),
|
|
16079
|
-
height: barThickness,
|
|
16080
|
-
direction: "horizontal"
|
|
16081
|
-
});
|
|
16082
|
-
return slots;
|
|
16508
|
+
function isTransparent(color) {
|
|
16509
|
+
return !color || color.a < 0.05;
|
|
16510
|
+
}
|
|
16511
|
+
function hasOpaqueBackground(background) {
|
|
16512
|
+
if (!background) return false;
|
|
16513
|
+
const value = background.trim().toLowerCase();
|
|
16514
|
+
if (!value || value === "transparent" || value === "rgba(0, 0, 0, 0)" || value === "rgb(0, 0, 0, 0)") {
|
|
16515
|
+
return false;
|
|
16083
16516
|
}
|
|
16084
|
-
const
|
|
16085
|
-
|
|
16086
|
-
|
|
16087
|
-
|
|
16088
|
-
|
|
16089
|
-
|
|
16090
|
-
|
|
16091
|
-
|
|
16092
|
-
|
|
16093
|
-
|
|
16094
|
-
|
|
16095
|
-
|
|
16096
|
-
|
|
16097
|
-
|
|
16098
|
-
|
|
16099
|
-
|
|
16100
|
-
|
|
16101
|
-
|
|
16102
|
-
|
|
16103
|
-
|
|
16104
|
-
|
|
16105
|
-
|
|
16106
|
-
|
|
16107
|
-
|
|
16108
|
-
|
|
16109
|
-
|
|
16110
|
-
|
|
16517
|
+
const parsed = parseColor(background);
|
|
16518
|
+
if (parsed) return !isTransparent(parsed);
|
|
16519
|
+
return true;
|
|
16520
|
+
}
|
|
16521
|
+
function toCss(color) {
|
|
16522
|
+
const r2 = Math.round(color.r);
|
|
16523
|
+
const g = Math.round(color.g);
|
|
16524
|
+
const b = Math.round(color.b);
|
|
16525
|
+
if (color.a >= 0.995) return `rgb(${r2}, ${g}, ${b})`;
|
|
16526
|
+
return `rgba(${r2}, ${g}, ${b}, ${Math.round(color.a * 100) / 100})`;
|
|
16527
|
+
}
|
|
16528
|
+
function colorKey(input) {
|
|
16529
|
+
const parsed = parseColor(input);
|
|
16530
|
+
if (!parsed || isTransparent(parsed)) return "transparent";
|
|
16531
|
+
return `${Math.round(parsed.r / 8)}-${Math.round(parsed.g / 8)}-${Math.round(parsed.b / 8)}-${Math.round(parsed.a * 4)}`;
|
|
16532
|
+
}
|
|
16533
|
+
function declaredVariant(className) {
|
|
16534
|
+
const match = className.match(/\bbtn--(primary|secondary|ghost)\b/);
|
|
16535
|
+
return match && isButtonVariantId(match[1]) ? match[1] : null;
|
|
16536
|
+
}
|
|
16537
|
+
function fillSlot(sample) {
|
|
16538
|
+
const width = parseFloat(sample.borderWidth);
|
|
16539
|
+
const border = parseColor(sample.borderColor);
|
|
16540
|
+
if (width > 0 && !isTransparent(border)) return "secondary";
|
|
16541
|
+
if (hasOpaqueBackground(sample.background)) return "primary";
|
|
16542
|
+
return "ghost";
|
|
16543
|
+
}
|
|
16544
|
+
function sampleSlot(sample) {
|
|
16545
|
+
return declaredVariant(sample.className) ?? fillSlot(sample);
|
|
16546
|
+
}
|
|
16547
|
+
function fingerprint(sample) {
|
|
16548
|
+
const width = parseFloat(sample.borderWidth);
|
|
16549
|
+
const border = width > 0 ? colorKey(sample.borderColor) : "none";
|
|
16550
|
+
return `${colorKey(sample.background)}|${border}|${colorKey(sample.color)}|${sampleSlot(sample)}`;
|
|
16551
|
+
}
|
|
16552
|
+
function paintColor(chrome) {
|
|
16553
|
+
if (hasOpaqueBackground(chrome.background)) {
|
|
16554
|
+
const parsed = parseColor(chrome.background);
|
|
16555
|
+
return parsed ? toCss({ ...parsed, a: 1 }) : chrome.background;
|
|
16556
|
+
}
|
|
16557
|
+
const width = parseFloat(chrome.borderWidth);
|
|
16558
|
+
if (width > 0 && hasOpaqueBackground(chrome.borderColor)) {
|
|
16559
|
+
const parsed = parseColor(chrome.borderColor);
|
|
16560
|
+
return parsed ? toCss({ ...parsed, a: 1 }) : chrome.borderColor;
|
|
16561
|
+
}
|
|
16562
|
+
const text = parseColor(chrome.color);
|
|
16563
|
+
return text ? toCss({ ...text, a: 1 }) : chrome.color;
|
|
16564
|
+
}
|
|
16565
|
+
function accentColor(chrome) {
|
|
16566
|
+
const bg = parseColor(chrome.background);
|
|
16567
|
+
if (bg && !isTransparent(bg) && relativeLuminance(bg) < 0.55) {
|
|
16568
|
+
return toCss({ ...bg, a: 1 });
|
|
16569
|
+
}
|
|
16570
|
+
const text = parseColor(chrome.color);
|
|
16571
|
+
if (text && !isTransparent(text)) return toCss({ ...text, a: 1 });
|
|
16572
|
+
return paintColor(chrome);
|
|
16573
|
+
}
|
|
16574
|
+
function chromeFrom(sample) {
|
|
16575
|
+
return {
|
|
16576
|
+
background: sample.background || TRANSPARENT,
|
|
16577
|
+
color: sample.color || "currentColor",
|
|
16578
|
+
borderColor: sample.borderColor || TRANSPARENT,
|
|
16579
|
+
borderWidth: sample.borderWidth || "0px"
|
|
16580
|
+
};
|
|
16581
|
+
}
|
|
16582
|
+
function filledPrimary(seed) {
|
|
16583
|
+
const paint = parseColor(paintColor(seed)) ?? { r: 15, g: 15, b: 15, a: 1 };
|
|
16584
|
+
const luminance = relativeLuminance(paint);
|
|
16585
|
+
return {
|
|
16586
|
+
background: toCss({ ...paint, a: 1 }),
|
|
16587
|
+
color: luminance > 0.55 ? "rgb(15, 15, 15)" : "rgb(255, 255, 255)",
|
|
16588
|
+
borderColor: TRANSPARENT,
|
|
16589
|
+
borderWidth: "0px"
|
|
16590
|
+
};
|
|
16591
|
+
}
|
|
16592
|
+
function generatedSecondary(primary) {
|
|
16593
|
+
const paint = accentColor(primary);
|
|
16594
|
+
return {
|
|
16595
|
+
background: TRANSPARENT,
|
|
16596
|
+
color: paint,
|
|
16597
|
+
borderColor: paint,
|
|
16598
|
+
borderWidth: "1px"
|
|
16599
|
+
};
|
|
16600
|
+
}
|
|
16601
|
+
function generatedGhost(primary) {
|
|
16602
|
+
return {
|
|
16603
|
+
background: TRANSPARENT,
|
|
16604
|
+
color: accentColor(primary),
|
|
16605
|
+
borderColor: TRANSPARENT,
|
|
16606
|
+
borderWidth: "0px"
|
|
16607
|
+
};
|
|
16608
|
+
}
|
|
16609
|
+
function normalizeOutlineChrome(outline, primary) {
|
|
16610
|
+
const paint = accentColor(primary);
|
|
16611
|
+
const text = parseColor(outline.color);
|
|
16612
|
+
const paintRgb = parseColor(paint);
|
|
16613
|
+
const primaryLabel = parseColor(primary.color);
|
|
16614
|
+
const matchesOnPrimary = Boolean(text && primaryLabel) && colorKey(outline.color) === colorKey(primary.color);
|
|
16615
|
+
const textTooLight = text ? relativeLuminance(text) > 0.7 : false;
|
|
16616
|
+
const paintIsDarker = paintRgb ? relativeLuminance(paintRgb) < 0.65 : hasOpaqueBackground(primary.background);
|
|
16617
|
+
if (!(matchesOnPrimary || textTooLight) || !paintIsDarker) return outline;
|
|
16618
|
+
const hasBorder = parseFloat(outline.borderWidth) > 0;
|
|
16619
|
+
return {
|
|
16620
|
+
...outline,
|
|
16621
|
+
color: paint,
|
|
16622
|
+
borderColor: hasBorder ? paint : outline.borderColor
|
|
16623
|
+
};
|
|
16624
|
+
}
|
|
16625
|
+
function generateButtonVariants(samples) {
|
|
16626
|
+
if (samples.length === 0) return { status: "unresolved" };
|
|
16627
|
+
const groups = /* @__PURE__ */ new Map();
|
|
16628
|
+
for (const sample of samples) {
|
|
16629
|
+
const key = fingerprint(sample);
|
|
16630
|
+
const list = groups.get(key) ?? [];
|
|
16631
|
+
list.push(sample);
|
|
16632
|
+
groups.set(key, list);
|
|
16633
|
+
}
|
|
16634
|
+
if (groups.size > 3) return { status: "unresolved" };
|
|
16635
|
+
const bySlot = /* @__PURE__ */ new Map();
|
|
16636
|
+
for (const group of groups.values()) {
|
|
16637
|
+
const sample = group[0];
|
|
16638
|
+
const slot = sampleSlot(sample);
|
|
16639
|
+
if (bySlot.has(slot)) return { status: "unresolved" };
|
|
16640
|
+
bySlot.set(slot, sample);
|
|
16641
|
+
}
|
|
16642
|
+
const primarySample = bySlot.get("primary");
|
|
16643
|
+
const seed = chromeFrom(primarySample ?? samples[0]);
|
|
16644
|
+
const primary = primarySample ? seed : filledPrimary(seed);
|
|
16645
|
+
const secondary = normalizeOutlineChrome(
|
|
16646
|
+
bySlot.has("secondary") ? chromeFrom(bySlot.get("secondary")) : generatedSecondary(primary),
|
|
16647
|
+
primary
|
|
16648
|
+
);
|
|
16649
|
+
const ghost = normalizeOutlineChrome(
|
|
16650
|
+
bySlot.has("ghost") ? chromeFrom(bySlot.get("ghost")) : generatedGhost(primary),
|
|
16651
|
+
primary
|
|
16652
|
+
);
|
|
16653
|
+
return {
|
|
16654
|
+
status: "ready",
|
|
16655
|
+
tokens: { primary, secondary, ghost }
|
|
16656
|
+
};
|
|
16657
|
+
}
|
|
16658
|
+
function geometryFromSample(sample) {
|
|
16659
|
+
return {
|
|
16660
|
+
paddingTop: px(sample.paddingTop),
|
|
16661
|
+
paddingRight: px(sample.paddingRight),
|
|
16662
|
+
paddingBottom: px(sample.paddingBottom),
|
|
16663
|
+
paddingLeft: px(sample.paddingLeft),
|
|
16664
|
+
fontSize: px(sample.fontSize),
|
|
16665
|
+
borderRadius: px(sample.borderRadius),
|
|
16666
|
+
gap: px(sample.gap),
|
|
16667
|
+
height: Math.round(sample.height)
|
|
16668
|
+
};
|
|
16669
|
+
}
|
|
16670
|
+
function shiftSample(base, steps) {
|
|
16671
|
+
return {
|
|
16672
|
+
height: Math.max(24, base.height + steps * 8),
|
|
16673
|
+
paddingTop: Math.max(0, base.paddingTop + steps * 4),
|
|
16674
|
+
paddingBottom: Math.max(0, base.paddingBottom + steps * 4),
|
|
16675
|
+
paddingLeft: Math.max(0, base.paddingLeft + steps * 8),
|
|
16676
|
+
paddingRight: Math.max(0, base.paddingRight + steps * 8),
|
|
16677
|
+
fontSize: base.fontSize,
|
|
16678
|
+
borderRadius: base.borderRadius,
|
|
16679
|
+
gap: base.gap
|
|
16680
|
+
};
|
|
16681
|
+
}
|
|
16682
|
+
function clusterSizes(samples) {
|
|
16683
|
+
const sorted = [...samples].sort((a, b) => a.height - b.height);
|
|
16684
|
+
const clusters = [];
|
|
16685
|
+
for (const sample of sorted) {
|
|
16686
|
+
const current = clusters[clusters.length - 1];
|
|
16687
|
+
const head = current?.[0];
|
|
16688
|
+
if (!current || !head || Math.abs(sample.height - head.height) > 2) clusters.push([sample]);
|
|
16689
|
+
else current.push(sample);
|
|
16690
|
+
}
|
|
16691
|
+
return clusters.map((group) => {
|
|
16692
|
+
const pick = (key) => group.reduce((sum, item) => sum + item[key], 0) / group.length;
|
|
16693
|
+
return {
|
|
16694
|
+
height: pick("height"),
|
|
16695
|
+
paddingTop: pick("paddingTop"),
|
|
16696
|
+
paddingRight: pick("paddingRight"),
|
|
16697
|
+
paddingBottom: pick("paddingBottom"),
|
|
16698
|
+
paddingLeft: pick("paddingLeft"),
|
|
16699
|
+
fontSize: pick("fontSize"),
|
|
16700
|
+
borderRadius: pick("borderRadius"),
|
|
16701
|
+
gap: pick("gap")
|
|
16702
|
+
};
|
|
16703
|
+
});
|
|
16704
|
+
}
|
|
16705
|
+
function tokensFromSamples(bySlot, radius, gap) {
|
|
16706
|
+
const fill = (id) => {
|
|
16707
|
+
const sample = bySlot[id] ?? REFERENCE_SIZES[id];
|
|
16708
|
+
return geometryFromSample({ ...sample, borderRadius: radius, gap });
|
|
16709
|
+
};
|
|
16710
|
+
return { s: fill("s"), m: fill("m"), l: fill("l") };
|
|
16711
|
+
}
|
|
16712
|
+
function interpolateSizes(known) {
|
|
16713
|
+
const order = BUTTON_SIZE_IDS;
|
|
16714
|
+
const indexOf = (id) => order.indexOf(id);
|
|
16715
|
+
const sorted = [...known].sort((a, b) => indexOf(a.id) - indexOf(b.id));
|
|
16716
|
+
const left = sorted[0];
|
|
16717
|
+
const right = sorted[1];
|
|
16718
|
+
const span = indexOf(right.id) - indexOf(left.id);
|
|
16719
|
+
const step = (key) => (right.sample[key] - left.sample[key]) / span;
|
|
16720
|
+
const at = (index) => {
|
|
16721
|
+
const steps = index - indexOf(left.id);
|
|
16722
|
+
return {
|
|
16723
|
+
height: left.sample.height + step("height") * steps,
|
|
16724
|
+
paddingTop: Math.max(0, left.sample.paddingTop + step("paddingTop") * steps),
|
|
16725
|
+
paddingBottom: Math.max(0, left.sample.paddingBottom + step("paddingBottom") * steps),
|
|
16726
|
+
paddingLeft: Math.max(0, left.sample.paddingLeft + step("paddingLeft") * steps),
|
|
16727
|
+
paddingRight: Math.max(0, left.sample.paddingRight + step("paddingRight") * steps),
|
|
16728
|
+
fontSize: Math.max(10, left.sample.fontSize + step("fontSize") * steps),
|
|
16729
|
+
borderRadius: left.sample.borderRadius,
|
|
16730
|
+
gap: left.sample.gap
|
|
16731
|
+
};
|
|
16732
|
+
};
|
|
16733
|
+
const bySlot = {
|
|
16734
|
+
[left.id]: left.sample,
|
|
16735
|
+
[right.id]: { ...right.sample, borderRadius: left.sample.borderRadius, gap: left.sample.gap }
|
|
16736
|
+
};
|
|
16737
|
+
for (const id of order) {
|
|
16738
|
+
if (!bySlot[id]) bySlot[id] = at(indexOf(id));
|
|
16739
|
+
}
|
|
16740
|
+
return tokensFromSamples(bySlot, left.sample.borderRadius, left.sample.gap);
|
|
16741
|
+
}
|
|
16742
|
+
function generateButtonSizes(samples) {
|
|
16743
|
+
const clusters = clusterSizes(samples.filter((sample) => sample.height > 0));
|
|
16744
|
+
if (clusters.length === 0) {
|
|
16745
|
+
return { status: "ready", tokens: tokensFromSamples(REFERENCE_SIZES, 8, 8) };
|
|
16746
|
+
}
|
|
16747
|
+
if (clusters.length > 3) return { status: "unresolved" };
|
|
16748
|
+
if (clusters.length === 3) {
|
|
16749
|
+
const sorted = [...clusters].sort((a, b) => a.height - b.height);
|
|
16750
|
+
const radius = sorted[1].borderRadius;
|
|
16751
|
+
const gap = sorted[1].gap;
|
|
16752
|
+
return {
|
|
16753
|
+
status: "ready",
|
|
16754
|
+
tokens: {
|
|
16755
|
+
s: geometryFromSample({ ...sorted[0], borderRadius: radius, gap }),
|
|
16756
|
+
m: geometryFromSample({ ...sorted[1], borderRadius: radius, gap }),
|
|
16757
|
+
l: geometryFromSample({ ...sorted[2], borderRadius: radius, gap })
|
|
16758
|
+
}
|
|
16759
|
+
};
|
|
16760
|
+
}
|
|
16761
|
+
if (clusters.length === 1) {
|
|
16762
|
+
const known = clusters[0];
|
|
16763
|
+
const slot = classifyHeight(known.height);
|
|
16764
|
+
const offset = BUTTON_SIZE_IDS.indexOf(slot);
|
|
16765
|
+
const bySlot = Object.fromEntries(
|
|
16766
|
+
BUTTON_SIZE_IDS.map((id, index) => [id, shiftSample(known, index - offset)])
|
|
16767
|
+
);
|
|
16768
|
+
bySlot[slot] = known;
|
|
16769
|
+
return { status: "ready", tokens: tokensFromSamples(bySlot, known.borderRadius, known.gap) };
|
|
16770
|
+
}
|
|
16771
|
+
const mapped = clusters.map((sample) => ({ id: classifyHeight(sample.height), sample }));
|
|
16772
|
+
if (mapped[0].id === mapped[1].id) {
|
|
16773
|
+
const larger = clusters.slice().sort((a, b) => b.height - a.height)[0];
|
|
16774
|
+
return generateButtonSizes([larger]);
|
|
16775
|
+
}
|
|
16776
|
+
return { status: "ready", tokens: interpolateSizes(mapped) };
|
|
16777
|
+
}
|
|
16778
|
+
function parseJson(raw) {
|
|
16779
|
+
if (!raw) return null;
|
|
16780
|
+
try {
|
|
16781
|
+
return JSON.parse(raw);
|
|
16782
|
+
} catch {
|
|
16783
|
+
return null;
|
|
16784
|
+
}
|
|
16785
|
+
}
|
|
16786
|
+
function isChrome(value) {
|
|
16787
|
+
if (!value || typeof value !== "object") return false;
|
|
16788
|
+
const chrome = value;
|
|
16789
|
+
return typeof chrome.background === "string" && typeof chrome.color === "string";
|
|
16790
|
+
}
|
|
16791
|
+
function isGeometry(value) {
|
|
16792
|
+
if (!value || typeof value !== "object") return false;
|
|
16793
|
+
const geometry = value;
|
|
16794
|
+
return typeof geometry.paddingTop === "string" && typeof geometry.height === "number";
|
|
16795
|
+
}
|
|
16796
|
+
function readVariantTokens(content) {
|
|
16797
|
+
const parsed = parseJson(content[BUTTON_VARIANTS_KEY]);
|
|
16798
|
+
if (!parsed) return null;
|
|
16799
|
+
if (!BUTTON_VARIANT_IDS.every((id) => isChrome(parsed[id]))) return null;
|
|
16800
|
+
return parsed;
|
|
16801
|
+
}
|
|
16802
|
+
function readSizeTokens(content) {
|
|
16803
|
+
const parsed = parseJson(content[BUTTON_SIZES_KEY]);
|
|
16804
|
+
if (!parsed) return null;
|
|
16805
|
+
if (!BUTTON_SIZE_IDS.every((id) => isGeometry(parsed[id]))) return null;
|
|
16806
|
+
return parsed;
|
|
16807
|
+
}
|
|
16808
|
+
function readAssignments(content) {
|
|
16809
|
+
const parsed = parseJson(content[BUTTON_ASSIGNMENTS_KEY]);
|
|
16810
|
+
if (!parsed || typeof parsed !== "object") return {};
|
|
16811
|
+
const next = {};
|
|
16812
|
+
for (const [id, value] of Object.entries(parsed)) {
|
|
16813
|
+
if (!value || !isButtonVariantId(value.variant) || !isButtonSizeId(value.size)) continue;
|
|
16814
|
+
next[id] = { variant: value.variant, size: value.size };
|
|
16815
|
+
}
|
|
16816
|
+
return next;
|
|
16817
|
+
}
|
|
16818
|
+
function cssLength(style, prop) {
|
|
16819
|
+
return style.getPropertyValue(prop) || "0px";
|
|
16820
|
+
}
|
|
16821
|
+
function readVariantSample(el) {
|
|
16822
|
+
const style = getComputedStyle(el);
|
|
16823
|
+
return {
|
|
16824
|
+
background: style.backgroundColor,
|
|
16825
|
+
color: style.color,
|
|
16826
|
+
borderColor: style.borderTopColor,
|
|
16827
|
+
borderWidth: style.borderTopWidth,
|
|
16828
|
+
className: el.className || ""
|
|
16829
|
+
};
|
|
16830
|
+
}
|
|
16831
|
+
function readSizeSample(el) {
|
|
16832
|
+
const style = getComputedStyle(el);
|
|
16833
|
+
const rootFont = parsePx(getComputedStyle(el.ownerDocument.documentElement).fontSize) || 16;
|
|
16834
|
+
const rect = el.getBoundingClientRect();
|
|
16835
|
+
return {
|
|
16836
|
+
height: rect.height,
|
|
16837
|
+
paddingTop: parsePx(cssLength(style, "padding-top"), rootFont),
|
|
16838
|
+
paddingRight: parsePx(cssLength(style, "padding-right"), rootFont),
|
|
16839
|
+
paddingBottom: parsePx(cssLength(style, "padding-bottom"), rootFont),
|
|
16840
|
+
paddingLeft: parsePx(cssLength(style, "padding-left"), rootFont),
|
|
16841
|
+
fontSize: parsePx(style.fontSize, rootFont),
|
|
16842
|
+
borderRadius: parsePx(style.borderTopLeftRadius, rootFont),
|
|
16843
|
+
gap: parsePx(style.columnGap || style.gap, rootFont)
|
|
16844
|
+
};
|
|
16845
|
+
}
|
|
16846
|
+
function readTypography(el) {
|
|
16847
|
+
const style = getComputedStyle(el);
|
|
16848
|
+
return {
|
|
16849
|
+
fontFamily: style.fontFamily,
|
|
16850
|
+
fontWeight: style.fontWeight,
|
|
16851
|
+
letterSpacing: style.letterSpacing,
|
|
16852
|
+
textTransform: style.textTransform,
|
|
16853
|
+
textDecoration: style.textDecorationLine || style.textDecoration || "none"
|
|
16854
|
+
};
|
|
16855
|
+
}
|
|
16856
|
+
var buttonOriginByEl = /* @__PURE__ */ new WeakMap();
|
|
16857
|
+
var ORIGIN_ATTR = "data-ohw-btn-origin";
|
|
16858
|
+
function parseOriginAttr(raw) {
|
|
16859
|
+
if (!raw) return null;
|
|
16860
|
+
try {
|
|
16861
|
+
const value = JSON.parse(raw);
|
|
16862
|
+
if (!value?.variant || !value.size || !value.typography) return null;
|
|
16863
|
+
return value;
|
|
16864
|
+
} catch {
|
|
16865
|
+
return null;
|
|
16866
|
+
}
|
|
16867
|
+
}
|
|
16868
|
+
function measureLiveOrigin(el) {
|
|
16869
|
+
return {
|
|
16870
|
+
variant: readVariantSample(el),
|
|
16871
|
+
size: readSizeSample(el),
|
|
16872
|
+
typography: readTypography(el)
|
|
16873
|
+
};
|
|
16874
|
+
}
|
|
16875
|
+
function captureButtonOrigin(el) {
|
|
16876
|
+
const cached = buttonOriginByEl.get(el);
|
|
16877
|
+
if (cached) return cached;
|
|
16878
|
+
const fromAttr = parseOriginAttr(el.getAttribute(ORIGIN_ATTR));
|
|
16879
|
+
if (fromAttr) {
|
|
16880
|
+
buttonOriginByEl.set(el, fromAttr);
|
|
16881
|
+
return fromAttr;
|
|
16882
|
+
}
|
|
16883
|
+
const origin = measureLiveOrigin(el);
|
|
16884
|
+
buttonOriginByEl.set(el, origin);
|
|
16885
|
+
try {
|
|
16886
|
+
el.setAttribute(ORIGIN_ATTR, JSON.stringify(origin));
|
|
16887
|
+
} catch {
|
|
16888
|
+
}
|
|
16889
|
+
return origin;
|
|
16890
|
+
}
|
|
16891
|
+
function listStyleButtons(doc) {
|
|
16892
|
+
return Array.from(doc.querySelectorAll(CTA_BUTTON_SELECTOR)).filter((el) => {
|
|
16893
|
+
if (el.closest("[data-ohw-bridge], [data-ohw-bridge-root]")) return false;
|
|
16894
|
+
const rect = el.getBoundingClientRect();
|
|
16895
|
+
return rect.width > 0 && rect.height > 0;
|
|
16896
|
+
});
|
|
16897
|
+
}
|
|
16898
|
+
function generateTokensFromButtons(buttons) {
|
|
16899
|
+
const variants = generateButtonVariants(buttons.map(readVariantSample));
|
|
16900
|
+
const sizes = generateButtonSizes(buttons.map(readSizeSample));
|
|
16901
|
+
if (variants.status !== "ready" || sizes.status !== "ready") return { status: "unresolved" };
|
|
16902
|
+
return { status: "ready", tokens: { variants: variants.tokens, sizes: sizes.tokens } };
|
|
16903
|
+
}
|
|
16904
|
+
function tokensFromButton(el) {
|
|
16905
|
+
const origin = captureButtonOrigin(el);
|
|
16906
|
+
const sample = origin.variant;
|
|
16907
|
+
const variants = generateButtonVariants([sample]);
|
|
16908
|
+
const sizes = generateButtonSizes([origin.size]);
|
|
16909
|
+
const primary = chromeFrom(sample);
|
|
16910
|
+
return {
|
|
16911
|
+
variants: variants.status === "ready" ? variants.tokens : { primary, secondary: generatedSecondary(primary), ghost: generatedGhost(primary) },
|
|
16912
|
+
sizes: sizes.status === "ready" ? sizes.tokens : tokensFromSamples(REFERENCE_SIZES, 8, 8)
|
|
16913
|
+
};
|
|
16914
|
+
}
|
|
16915
|
+
function readStoredStyleTokens(content) {
|
|
16916
|
+
const variants = readVariantTokens(content);
|
|
16917
|
+
const sizes = readSizeTokens(content);
|
|
16918
|
+
if (!variants || !sizes) return null;
|
|
16919
|
+
return { variants, sizes };
|
|
16920
|
+
}
|
|
16921
|
+
function styleTokenNodes(tokens) {
|
|
16922
|
+
return [
|
|
16923
|
+
{ key: BUTTON_VARIANTS_KEY, text: JSON.stringify(tokens.variants) },
|
|
16924
|
+
{ key: BUTTON_SIZES_KEY, text: JSON.stringify(tokens.sizes) }
|
|
16925
|
+
];
|
|
16926
|
+
}
|
|
16927
|
+
function ensureButtonStyleTokens(doc, content) {
|
|
16928
|
+
const stored = readStoredStyleTokens(content);
|
|
16929
|
+
if (stored) return { tokens: stored, nodes: [] };
|
|
16930
|
+
const generated = generateTokensFromButtons(listStyleButtons(doc));
|
|
16931
|
+
if (generated.status !== "ready") return { tokens: null, nodes: [] };
|
|
16932
|
+
return { tokens: generated.tokens, nodes: styleTokenNodes(generated.tokens) };
|
|
16933
|
+
}
|
|
16934
|
+
function detectVariant(el, tokens) {
|
|
16935
|
+
const declared = declaredVariant(el.className || "");
|
|
16936
|
+
if (declared) return declared;
|
|
16937
|
+
const stamped = el.getAttribute("data-ohw-btn-variant");
|
|
16938
|
+
if (stamped && isButtonVariantId(stamped)) return stamped;
|
|
16939
|
+
const sample = readVariantSample(el);
|
|
16940
|
+
if (!tokens) return sampleSlot(sample);
|
|
16941
|
+
const key = fingerprint(sample);
|
|
16942
|
+
for (const id of BUTTON_VARIANT_IDS) {
|
|
16943
|
+
const chrome = tokens[id];
|
|
16944
|
+
const tokenKey = fingerprint({
|
|
16945
|
+
background: chrome.background,
|
|
16946
|
+
color: chrome.color,
|
|
16947
|
+
borderColor: chrome.borderColor,
|
|
16948
|
+
borderWidth: chrome.borderWidth,
|
|
16949
|
+
className: `btn btn--${id}`
|
|
16950
|
+
});
|
|
16951
|
+
if (tokenKey === key) return id;
|
|
16952
|
+
}
|
|
16953
|
+
return sampleSlot(sample);
|
|
16954
|
+
}
|
|
16955
|
+
function detectSize(el, tokens) {
|
|
16956
|
+
const stamped = el.getAttribute("data-ohw-btn-size");
|
|
16957
|
+
if (stamped && isButtonSizeId(stamped)) return stamped;
|
|
16958
|
+
const height = el.getBoundingClientRect().height;
|
|
16959
|
+
if (!tokens) return classifyHeight(height);
|
|
16960
|
+
let best = "m";
|
|
16961
|
+
let bestDelta = Number.POSITIVE_INFINITY;
|
|
16962
|
+
for (const id of BUTTON_SIZE_IDS) {
|
|
16963
|
+
const delta = Math.abs(tokens[id].height - height);
|
|
16964
|
+
if (delta < bestDelta) {
|
|
16965
|
+
best = id;
|
|
16966
|
+
bestDelta = delta;
|
|
16967
|
+
}
|
|
16968
|
+
}
|
|
16969
|
+
return best;
|
|
16970
|
+
}
|
|
16971
|
+
function assignmentFor(el, content, tokens) {
|
|
16972
|
+
const id = buttonId(el);
|
|
16973
|
+
const stored = id ? readAssignments(content)[id] : void 0;
|
|
16974
|
+
if (stored) return stored;
|
|
16975
|
+
return {
|
|
16976
|
+
variant: detectVariant(el, tokens?.variants ?? null),
|
|
16977
|
+
size: detectSize(el, tokens?.sizes ?? null)
|
|
16978
|
+
};
|
|
16979
|
+
}
|
|
16980
|
+
function labelElement(el) {
|
|
16981
|
+
return el.querySelector('[data-ohw-editable="text"], [data-ohw-editable="plain"]') ?? (el.matches('[data-ohw-editable="text"], [data-ohw-editable="plain"]') ? el : null);
|
|
16982
|
+
}
|
|
16983
|
+
var paintLockByEl = /* @__PURE__ */ new WeakMap();
|
|
16984
|
+
var paintObserverByEl = /* @__PURE__ */ new WeakMap();
|
|
16985
|
+
var paintingButton = false;
|
|
16986
|
+
function paintButtonChrome(el, assignment, tokens) {
|
|
16987
|
+
const origin = captureButtonOrigin(el);
|
|
16988
|
+
const chrome = tokens.variants[assignment.variant];
|
|
16989
|
+
const originSlot = classifyHeight(origin.size.height);
|
|
16990
|
+
const geometry = assignment.size === originSlot ? geometryFromSample({ ...origin.size, borderRadius: origin.size.borderRadius, gap: origin.size.gap }) : tokens.sizes[assignment.size];
|
|
16991
|
+
const { typography } = origin;
|
|
16992
|
+
el.setAttribute("data-ohw-btn-variant", assignment.variant);
|
|
16993
|
+
el.setAttribute("data-ohw-btn-size", assignment.size);
|
|
16994
|
+
el.style.transition = "none";
|
|
16995
|
+
el.style.boxSizing = "border-box";
|
|
16996
|
+
el.style.display = "inline-flex";
|
|
16997
|
+
el.style.alignItems = "center";
|
|
16998
|
+
el.style.justifyContent = "center";
|
|
16999
|
+
el.style.background = chrome.background;
|
|
17000
|
+
el.style.color = chrome.color;
|
|
17001
|
+
el.style.borderStyle = parseFloat(chrome.borderWidth) > 0 ? "solid" : "none";
|
|
17002
|
+
el.style.borderColor = chrome.borderColor;
|
|
17003
|
+
el.style.borderWidth = chrome.borderWidth;
|
|
17004
|
+
el.style.padding = `${geometry.paddingTop} ${geometry.paddingRight} ${geometry.paddingBottom} ${geometry.paddingLeft}`;
|
|
17005
|
+
el.style.fontSize = geometry.fontSize;
|
|
17006
|
+
el.style.borderRadius = px(origin.size.borderRadius);
|
|
17007
|
+
el.style.gap = geometry.gap;
|
|
17008
|
+
el.style.height = px(geometry.height);
|
|
17009
|
+
el.style.fontFamily = typography.fontFamily;
|
|
17010
|
+
el.style.fontWeight = typography.fontWeight;
|
|
17011
|
+
el.style.letterSpacing = typography.letterSpacing;
|
|
17012
|
+
el.style.textTransform = typography.textTransform;
|
|
17013
|
+
if (typography.textDecoration && typography.textDecoration !== "none") {
|
|
17014
|
+
el.style.textDecoration = typography.textDecoration;
|
|
17015
|
+
} else {
|
|
17016
|
+
el.style.textDecoration = "none";
|
|
17017
|
+
}
|
|
17018
|
+
const label = labelElement(el);
|
|
17019
|
+
if (label && label !== el) label.style.color = chrome.color;
|
|
17020
|
+
}
|
|
17021
|
+
function guardTemplateHover(el) {
|
|
17022
|
+
if (paintObserverByEl.has(el)) return;
|
|
17023
|
+
const observer = new MutationObserver(() => {
|
|
17024
|
+
if (paintingButton) return;
|
|
17025
|
+
const lock = paintLockByEl.get(el);
|
|
17026
|
+
if (!lock) return;
|
|
17027
|
+
paintingButton = true;
|
|
17028
|
+
paintButtonChrome(el, lock.assignment, lock.tokens);
|
|
17029
|
+
paintingButton = false;
|
|
17030
|
+
});
|
|
17031
|
+
observer.observe(el, { attributes: true, attributeFilter: ["style", "class"] });
|
|
17032
|
+
paintObserverByEl.set(el, observer);
|
|
17033
|
+
}
|
|
17034
|
+
function paintedTokensOf(el) {
|
|
17035
|
+
return paintLockByEl.get(el)?.tokens ?? null;
|
|
17036
|
+
}
|
|
17037
|
+
function applyButtonStyle(el, assignment, tokens) {
|
|
17038
|
+
paintLockByEl.set(el, { assignment, tokens });
|
|
17039
|
+
paintingButton = true;
|
|
17040
|
+
paintButtonChrome(el, assignment, tokens);
|
|
17041
|
+
paintingButton = false;
|
|
17042
|
+
guardTemplateHover(el);
|
|
17043
|
+
}
|
|
17044
|
+
function applyButtonStylesFromContent(doc, content) {
|
|
17045
|
+
const assignments = readAssignments(content);
|
|
17046
|
+
for (const [id, assignment] of Object.entries(assignments)) {
|
|
17047
|
+
const el = doc.querySelector(`[data-ohw-href-key="${CSS.escape(id)}"]`);
|
|
17048
|
+
if (!el) continue;
|
|
17049
|
+
applyButtonStyle(el, assignment, tokensFromButton(el));
|
|
17050
|
+
}
|
|
17051
|
+
}
|
|
17052
|
+
function withAssignment(content, id, assignment) {
|
|
17053
|
+
return { ...readAssignments(content), [id]: assignment };
|
|
17054
|
+
}
|
|
17055
|
+
|
|
17056
|
+
// src/ui/button-style-panel.tsx
|
|
17057
|
+
import { jsx as jsx31, jsxs as jsxs21 } from "react/jsx-runtime";
|
|
17058
|
+
var SIZE_LABEL = { s: "S", m: "M", l: "L" };
|
|
17059
|
+
function ButtonStylePanel({
|
|
17060
|
+
variants,
|
|
17061
|
+
sizes,
|
|
17062
|
+
variant,
|
|
17063
|
+
size,
|
|
17064
|
+
onVariant,
|
|
17065
|
+
onSize,
|
|
17066
|
+
previewLabel = "Book Now",
|
|
17067
|
+
slotBackground = "var(--brand-background, var(--ohw-brand-light, var(--color-light, #ffffff)))"
|
|
17068
|
+
}) {
|
|
17069
|
+
const preview = scaleGeometry(sizes.m, 0.75);
|
|
17070
|
+
const label = previewLabel.trim() || "Book Now";
|
|
17071
|
+
return /* @__PURE__ */ jsxs21("div", { className: "flex w-full flex-col gap-5", children: [
|
|
17072
|
+
/* @__PURE__ */ jsxs21("section", { className: "flex w-full flex-col gap-2.5", children: [
|
|
17073
|
+
/* @__PURE__ */ jsx31("h3", { className: "text-xs font-semibold uppercase leading-4 tracking-[0.6px] text-stone-500 font-sans", children: "Variants" }),
|
|
17074
|
+
/* @__PURE__ */ jsx31("div", { className: "flex w-full flex-col gap-2.5", children: BUTTON_VARIANT_IDS.map((id) => {
|
|
17075
|
+
const chrome = variants[id];
|
|
17076
|
+
const selected = id === variant;
|
|
17077
|
+
const hasBorder = parseFloat(chrome.borderWidth) > 0;
|
|
17078
|
+
const cardSlot = previewSlotForChrome(chrome, slotBackground);
|
|
17079
|
+
return /* @__PURE__ */ jsxs21(
|
|
17080
|
+
"button",
|
|
17081
|
+
{
|
|
17082
|
+
type: "button",
|
|
17083
|
+
"aria-pressed": selected,
|
|
17084
|
+
"aria-label": id,
|
|
17085
|
+
onMouseDown: (e) => {
|
|
17086
|
+
e.preventDefault();
|
|
17087
|
+
e.stopPropagation();
|
|
17088
|
+
},
|
|
17089
|
+
onClick: () => onVariant(id),
|
|
17090
|
+
className: cn(
|
|
17091
|
+
"relative w-full overflow-hidden rounded-xl border-solid text-left",
|
|
17092
|
+
selected ? "border-2 border-primary" : "border border-border"
|
|
17093
|
+
),
|
|
17094
|
+
children: [
|
|
17095
|
+
/* @__PURE__ */ jsx31(
|
|
17096
|
+
"div",
|
|
17097
|
+
{
|
|
17098
|
+
className: "flex w-full items-center justify-center py-4",
|
|
17099
|
+
style: { background: cardSlot },
|
|
17100
|
+
children: /* @__PURE__ */ jsx31(
|
|
17101
|
+
"span",
|
|
17102
|
+
{
|
|
17103
|
+
className: "inline-flex items-center justify-center whitespace-nowrap font-semibold uppercase leading-none",
|
|
17104
|
+
style: {
|
|
17105
|
+
background: chrome.background,
|
|
17106
|
+
color: chrome.color,
|
|
17107
|
+
borderColor: chrome.borderColor,
|
|
17108
|
+
borderWidth: hasBorder ? chrome.borderWidth : "0px",
|
|
17109
|
+
borderStyle: hasBorder ? "solid" : "none",
|
|
17110
|
+
padding: `${preview.paddingTop} ${preview.paddingRight} ${preview.paddingBottom} ${preview.paddingLeft}`,
|
|
17111
|
+
fontSize: preview.fontSize,
|
|
17112
|
+
borderRadius: preview.borderRadius,
|
|
17113
|
+
height: preview.height,
|
|
17114
|
+
boxSizing: "border-box",
|
|
17115
|
+
letterSpacing: "0.12em"
|
|
17116
|
+
},
|
|
17117
|
+
children: label
|
|
17118
|
+
}
|
|
17119
|
+
)
|
|
17120
|
+
}
|
|
17121
|
+
),
|
|
17122
|
+
selected ? /* @__PURE__ */ jsx31(
|
|
17123
|
+
"span",
|
|
17124
|
+
{
|
|
17125
|
+
className: "absolute right-0.5 top-0.5 flex size-5 items-center justify-center rounded-full bg-primary text-primary-foreground",
|
|
17126
|
+
"aria-hidden": true,
|
|
17127
|
+
children: /* @__PURE__ */ jsx31(Check3, { className: "size-3", strokeWidth: 3 })
|
|
17128
|
+
}
|
|
17129
|
+
) : null
|
|
17130
|
+
]
|
|
17131
|
+
},
|
|
17132
|
+
id
|
|
17133
|
+
);
|
|
17134
|
+
}) })
|
|
17135
|
+
] }),
|
|
17136
|
+
/* @__PURE__ */ jsxs21("section", { className: "flex w-full flex-col gap-2.5", children: [
|
|
17137
|
+
/* @__PURE__ */ jsx31("h3", { className: "text-xs font-semibold uppercase leading-4 tracking-[0.6px] text-stone-500 font-sans", children: "Size" }),
|
|
17138
|
+
/* @__PURE__ */ jsx31(
|
|
17139
|
+
"div",
|
|
17140
|
+
{
|
|
17141
|
+
className: "flex w-full items-start rounded-lg bg-stone-100 p-1",
|
|
17142
|
+
role: "radiogroup",
|
|
17143
|
+
"aria-label": "Size",
|
|
17144
|
+
children: BUTTON_SIZE_IDS.map((id) => {
|
|
17145
|
+
const selected = id === size;
|
|
17146
|
+
return /* @__PURE__ */ jsx31(
|
|
17147
|
+
"button",
|
|
17148
|
+
{
|
|
17149
|
+
type: "button",
|
|
17150
|
+
role: "radio",
|
|
17151
|
+
"aria-checked": selected,
|
|
17152
|
+
onMouseDown: (e) => {
|
|
17153
|
+
e.preventDefault();
|
|
17154
|
+
e.stopPropagation();
|
|
17155
|
+
},
|
|
17156
|
+
onClick: () => onSize(id),
|
|
17157
|
+
className: cn(
|
|
17158
|
+
"flex min-w-14 flex-1 items-center justify-center rounded-md px-3 py-1.5 text-sm font-medium leading-5",
|
|
17159
|
+
selected ? "bg-white text-stone-950 shadow-sm" : "bg-transparent text-stone-500"
|
|
17160
|
+
),
|
|
17161
|
+
children: SIZE_LABEL[id]
|
|
17162
|
+
},
|
|
17163
|
+
id
|
|
17164
|
+
);
|
|
17165
|
+
})
|
|
17166
|
+
}
|
|
17167
|
+
)
|
|
17168
|
+
] })
|
|
17169
|
+
] });
|
|
17170
|
+
}
|
|
17171
|
+
|
|
17172
|
+
// src/lib/button-collections.ts
|
|
17173
|
+
var BUTTON_COLLECTIONS_KEY = "__ohw_button_collections";
|
|
17174
|
+
var BUTTON_SNAPSHOTS_KEY = "__ohw_button_snapshots";
|
|
17175
|
+
var BUTTON_HIDDEN_KEY = "__ohw_button_hidden";
|
|
17176
|
+
var COLLECTION_ATTR = "data-ohw-button-collection";
|
|
17177
|
+
function parseJson2(raw) {
|
|
17178
|
+
if (!raw) return null;
|
|
17179
|
+
try {
|
|
17180
|
+
return JSON.parse(raw);
|
|
17181
|
+
} catch {
|
|
17182
|
+
return null;
|
|
17183
|
+
}
|
|
17184
|
+
}
|
|
17185
|
+
function readCollections(content) {
|
|
17186
|
+
const parsed = parseJson2(content[BUTTON_COLLECTIONS_KEY]);
|
|
17187
|
+
if (!parsed || typeof parsed !== "object") return {};
|
|
17188
|
+
const next = {};
|
|
17189
|
+
for (const [id, value] of Object.entries(parsed)) {
|
|
17190
|
+
if (!value || !Array.isArray(value.members)) continue;
|
|
17191
|
+
next[id] = {
|
|
17192
|
+
id,
|
|
17193
|
+
members: value.members.filter((member) => typeof member === "string" && member),
|
|
17194
|
+
gap: typeof value.gap === "string" ? value.gap : "12px"
|
|
17195
|
+
};
|
|
17196
|
+
}
|
|
17197
|
+
return next;
|
|
17198
|
+
}
|
|
17199
|
+
function readSnapshots(content) {
|
|
17200
|
+
const parsed = parseJson2(content[BUTTON_SNAPSHOTS_KEY]);
|
|
17201
|
+
if (!parsed || typeof parsed !== "object") return {};
|
|
17202
|
+
const next = {};
|
|
17203
|
+
for (const [id, value] of Object.entries(parsed)) {
|
|
17204
|
+
if (!value || typeof value.html !== "string") continue;
|
|
17205
|
+
next[id] = value;
|
|
17206
|
+
}
|
|
17207
|
+
return next;
|
|
17208
|
+
}
|
|
17209
|
+
function readHiddenButtons(content) {
|
|
17210
|
+
const parsed = parseJson2(content[BUTTON_HIDDEN_KEY]);
|
|
17211
|
+
if (!Array.isArray(parsed)) return [];
|
|
17212
|
+
return parsed.filter((id) => typeof id === "string" && id);
|
|
17213
|
+
}
|
|
17214
|
+
function buttonCollectionOf(el) {
|
|
17215
|
+
return el?.closest(`[${COLLECTION_ATTR}]`) ?? null;
|
|
17216
|
+
}
|
|
17217
|
+
function isNavbarCta(el) {
|
|
17218
|
+
return el.getAttribute("data-ohw-role") === "navbar-button" || Boolean(el.closest('[data-ohw-role="navbar-button"]'));
|
|
17219
|
+
}
|
|
17220
|
+
function navbarScope(el) {
|
|
17221
|
+
return el.closest("nav, [data-ohw-nav-container], [data-ohw-nav-drawer]") ?? el.ownerDocument;
|
|
17222
|
+
}
|
|
17223
|
+
function isLastNavbarButton(el) {
|
|
17224
|
+
if (!isNavbarCta(el)) return false;
|
|
17225
|
+
const buttons = Array.from(navbarScope(el).querySelectorAll(CTA_BUTTON_SELECTOR)).filter(
|
|
17226
|
+
(button) => isNavbarCta(button) && buttonId(button)
|
|
17227
|
+
);
|
|
17228
|
+
return buttons.length <= 1;
|
|
17229
|
+
}
|
|
17230
|
+
function canDeleteButton(el) {
|
|
17231
|
+
return !isLastNavbarButton(el);
|
|
17232
|
+
}
|
|
17233
|
+
function canDuplicateButton(el) {
|
|
17234
|
+
return isNavbarCta(el);
|
|
17235
|
+
}
|
|
17236
|
+
function labelElement2(el) {
|
|
17237
|
+
return el.querySelector('[data-ohw-editable="text"], [data-ohw-editable="plain"]') ?? el.querySelector("[data-ohw-key]");
|
|
17238
|
+
}
|
|
17239
|
+
function buttonLabel(el) {
|
|
17240
|
+
return (labelElement2(el)?.textContent ?? el.textContent ?? "").trim();
|
|
17241
|
+
}
|
|
17242
|
+
function buttonHref(el) {
|
|
17243
|
+
return el.getAttribute("href") ?? "";
|
|
17244
|
+
}
|
|
17245
|
+
function hrefKeyBase(hrefKey) {
|
|
17246
|
+
return hrefKey.replace(/-href$/, "").replace(/-copy-\d+$/, "");
|
|
17247
|
+
}
|
|
17248
|
+
function labelKeyForHrefKey(hrefKey) {
|
|
17249
|
+
return `${hrefKey.replace(/-href$/, "")}-label`;
|
|
17250
|
+
}
|
|
17251
|
+
function cleanClone(el) {
|
|
17252
|
+
const copy = el.cloneNode(true);
|
|
17253
|
+
copy.querySelectorAll("[data-ohw-selected], [data-ohw-hovered], [data-ohw-editing]").forEach((node) => {
|
|
17254
|
+
node.removeAttribute("data-ohw-selected");
|
|
17255
|
+
node.removeAttribute("data-ohw-hovered");
|
|
17256
|
+
node.removeAttribute("data-ohw-editing");
|
|
17257
|
+
node.removeAttribute("contenteditable");
|
|
17258
|
+
});
|
|
17259
|
+
copy.removeAttribute("data-ohw-selected");
|
|
17260
|
+
copy.removeAttribute("data-ohw-hovered");
|
|
17261
|
+
copy.removeAttribute("data-ohw-editing");
|
|
17262
|
+
copy.removeAttribute("contenteditable");
|
|
17263
|
+
copy.removeAttribute("data-ohw-drag-disabled");
|
|
17264
|
+
return copy;
|
|
17265
|
+
}
|
|
17266
|
+
function nextCopyId(sourceId, content, doc) {
|
|
17267
|
+
const used = /* @__PURE__ */ new Set([
|
|
17268
|
+
...Object.keys(readSnapshots(content)),
|
|
17269
|
+
...Object.keys(readAssignments(content)),
|
|
17270
|
+
...Array.from(doc.querySelectorAll("[data-ohw-href-key]")).map(
|
|
17271
|
+
(el) => el.getAttribute("data-ohw-href-key") ?? ""
|
|
17272
|
+
)
|
|
17273
|
+
]);
|
|
17274
|
+
const base = hrefKeyBase(sourceId);
|
|
17275
|
+
let n = 2;
|
|
17276
|
+
while (used.has(`${base}-copy-${n}-href`)) n += 1;
|
|
17277
|
+
return `${base}-copy-${n}-href`;
|
|
17278
|
+
}
|
|
17279
|
+
function nextCollectionId(content, doc) {
|
|
17280
|
+
const used = /* @__PURE__ */ new Set([
|
|
17281
|
+
...Object.keys(readCollections(content)),
|
|
17282
|
+
...Array.from(doc.querySelectorAll(`[${COLLECTION_ATTR}]`)).map(
|
|
17283
|
+
(el) => el.getAttribute(COLLECTION_ATTR) ?? ""
|
|
17284
|
+
)
|
|
17285
|
+
]);
|
|
17286
|
+
let n = 1;
|
|
17287
|
+
while (used.has(`bc-${n}`)) n += 1;
|
|
17288
|
+
return `bc-${n}`;
|
|
17289
|
+
}
|
|
17290
|
+
var COLLECTION_GAP_MAX_PX = 12;
|
|
17291
|
+
var COLLECTION_GAP_DEFAULT = "12px";
|
|
17292
|
+
function usableGap(value) {
|
|
17293
|
+
if (!value || value === "normal") return null;
|
|
17294
|
+
const n = parseFloat(value);
|
|
17295
|
+
if (!Number.isFinite(n) || n <= 0) return null;
|
|
17296
|
+
if (n > COLLECTION_GAP_MAX_PX) return COLLECTION_GAP_DEFAULT;
|
|
17297
|
+
return `${Math.round(n * 100) / 100}px`;
|
|
17298
|
+
}
|
|
17299
|
+
function collectionGap(el, tokens) {
|
|
17300
|
+
const fromCollection = usableGap(buttonCollectionOf(el)?.style.gap);
|
|
17301
|
+
if (fromCollection) return fromCollection;
|
|
17302
|
+
const parent = el.parentElement;
|
|
17303
|
+
if (parent) {
|
|
17304
|
+
const style = getComputedStyle(parent);
|
|
17305
|
+
const fromParent = usableGap(style.columnGap) ?? usableGap(style.gap);
|
|
17306
|
+
if (fromParent) return fromParent;
|
|
17307
|
+
}
|
|
17308
|
+
const fromTokens = usableGap(tokens?.sizes.m.gap);
|
|
17309
|
+
if (fromTokens) return fromTokens;
|
|
17310
|
+
return COLLECTION_GAP_DEFAULT;
|
|
17311
|
+
}
|
|
17312
|
+
function styleCollection(collection, gap) {
|
|
17313
|
+
collection.style.display = "inline-flex";
|
|
17314
|
+
collection.style.alignItems = "center";
|
|
17315
|
+
collection.style.flexWrap = "wrap";
|
|
17316
|
+
collection.style.gap = gap;
|
|
17317
|
+
collection.style.maxWidth = "100%";
|
|
17318
|
+
}
|
|
17319
|
+
function createCollection(doc, id, gap) {
|
|
17320
|
+
const collection = doc.createElement("div");
|
|
17321
|
+
collection.setAttribute(COLLECTION_ATTR, id);
|
|
17322
|
+
styleCollection(collection, gap);
|
|
17323
|
+
return collection;
|
|
17324
|
+
}
|
|
17325
|
+
function setButtonDragAttr(el) {
|
|
17326
|
+
if (isNavbarCta(el) && buttonCollectionOf(el)) el.removeAttribute("data-ohw-drag-disabled");
|
|
17327
|
+
else el.setAttribute("data-ohw-drag-disabled", "true");
|
|
17328
|
+
}
|
|
17329
|
+
function rekeyCopy(copy, id) {
|
|
17330
|
+
copy.setAttribute("data-ohw-href-key", id);
|
|
17331
|
+
const label = labelElement2(copy);
|
|
17332
|
+
const labelKey = labelKeyForHrefKey(id);
|
|
17333
|
+
if (label) label.setAttribute("data-ohw-key", labelKey);
|
|
17334
|
+
setButtonDragAttr(copy);
|
|
17335
|
+
return { labelKey };
|
|
17336
|
+
}
|
|
17337
|
+
function stampVariantClass(el, variant) {
|
|
17338
|
+
const raw = typeof el.className === "string" ? el.className : el.getAttribute("class") || "";
|
|
17339
|
+
const without = raw.replace(/\bbtn--(?:primary|secondary|ghost)\b/g, "").replace(/\s+/g, " ").trim();
|
|
17340
|
+
el.className = without ? `${without} btn--${variant}` : `btn btn--${variant}`;
|
|
17341
|
+
}
|
|
17342
|
+
function snapshotOf(el) {
|
|
17343
|
+
const id = buttonId(el) ?? "";
|
|
17344
|
+
const label = labelElement2(el);
|
|
17345
|
+
return {
|
|
17346
|
+
id,
|
|
17347
|
+
href: buttonHref(el),
|
|
17348
|
+
label: buttonLabel(el),
|
|
17349
|
+
labelKey: label?.getAttribute("data-ohw-key") ?? labelKeyForHrefKey(id),
|
|
17350
|
+
html: cleanClone(el).outerHTML
|
|
17351
|
+
};
|
|
17352
|
+
}
|
|
17353
|
+
function htmlToElement(doc, html) {
|
|
17354
|
+
const wrap = doc.createElement("div");
|
|
17355
|
+
wrap.innerHTML = html;
|
|
17356
|
+
const el = wrap.firstElementChild;
|
|
17357
|
+
return el instanceof HTMLElement ? el : null;
|
|
17358
|
+
}
|
|
17359
|
+
function findButton(doc, id) {
|
|
17360
|
+
return doc.querySelector(`[data-ohw-href-key="${CSS.escape(id)}"]`);
|
|
17361
|
+
}
|
|
17362
|
+
function duplicateButton(source, content) {
|
|
17363
|
+
if (!canDuplicateButton(source)) return null;
|
|
17364
|
+
const sourceId = buttonId(source);
|
|
17365
|
+
if (!sourceId) return null;
|
|
17366
|
+
const doc = source.ownerDocument;
|
|
17367
|
+
const tokens = tokensFromButton(source);
|
|
17368
|
+
const copyId = nextCopyId(sourceId, content, doc);
|
|
17369
|
+
const copy = cleanClone(source);
|
|
17370
|
+
const { labelKey } = rekeyCopy(copy, copyId);
|
|
17371
|
+
const href = buttonHref(source);
|
|
17372
|
+
const label = buttonLabel(source);
|
|
17373
|
+
if (href) copy.setAttribute("href", href);
|
|
17374
|
+
const sourceAssignment = readAssignments(content)[sourceId] ?? assignmentFor(source, content, tokens);
|
|
17375
|
+
const copyAssignment = { ...sourceAssignment };
|
|
17376
|
+
stampVariantClass(copy, copyAssignment.variant);
|
|
17377
|
+
applyButtonStyle(copy, copyAssignment, paintedTokensOf(source) ?? tokens);
|
|
17378
|
+
const copyLabelEl = labelElement2(copy);
|
|
17379
|
+
if (copyLabelEl) copyLabelEl.textContent = label;
|
|
17380
|
+
let collection = buttonCollectionOf(source);
|
|
17381
|
+
const collections = readCollections(content);
|
|
17382
|
+
let collectionId = collection?.getAttribute(COLLECTION_ATTR) ?? "";
|
|
17383
|
+
let members = collectionId && collections[collectionId] ? [...collections[collectionId].members] : [];
|
|
17384
|
+
const gap = collectionGap(source, tokens);
|
|
17385
|
+
if (!collection) {
|
|
17386
|
+
collectionId = nextCollectionId(content, doc);
|
|
17387
|
+
collection = createCollection(doc, collectionId, gap);
|
|
17388
|
+
source.parentElement?.insertBefore(collection, source);
|
|
17389
|
+
collection.append(source, copy);
|
|
17390
|
+
setButtonDragAttr(source);
|
|
17391
|
+
setButtonDragAttr(copy);
|
|
17392
|
+
members = [sourceId, copyId];
|
|
17393
|
+
} else {
|
|
17394
|
+
styleCollection(collection, gap);
|
|
17395
|
+
source.after(copy);
|
|
17396
|
+
setButtonDragAttr(copy);
|
|
17397
|
+
if (!members.includes(sourceId)) members = listCollectionMembers(collection);
|
|
17398
|
+
const at = members.indexOf(sourceId);
|
|
17399
|
+
members.splice(at >= 0 ? at + 1 : members.length, 0, copyId);
|
|
17400
|
+
}
|
|
17401
|
+
const sourceLabelKey = labelElement2(source)?.getAttribute("data-ohw-key");
|
|
17402
|
+
const snapshots = {
|
|
17403
|
+
...readSnapshots(content),
|
|
17404
|
+
[sourceId]: snapshotOf(source),
|
|
17405
|
+
[copyId]: snapshotOf(copy)
|
|
17406
|
+
};
|
|
17407
|
+
const nextCollections = {
|
|
17408
|
+
...collections,
|
|
17409
|
+
[collectionId]: { id: collectionId, members, gap }
|
|
17410
|
+
};
|
|
17411
|
+
const assignments = withAssignment(content, copyId, copyAssignment);
|
|
17412
|
+
const nextContent = {
|
|
17413
|
+
...content,
|
|
17414
|
+
[copyId]: href,
|
|
17415
|
+
[labelKey]: label,
|
|
17416
|
+
[BUTTON_COLLECTIONS_KEY]: JSON.stringify(nextCollections),
|
|
17417
|
+
[BUTTON_SNAPSHOTS_KEY]: JSON.stringify(snapshots),
|
|
17418
|
+
[BUTTON_ASSIGNMENTS_KEY]: JSON.stringify(assignments)
|
|
17419
|
+
};
|
|
17420
|
+
if (sourceLabelKey && nextContent[sourceLabelKey] === void 0) {
|
|
17421
|
+
nextContent[sourceLabelKey] = label;
|
|
17422
|
+
}
|
|
17423
|
+
const nodeKeys = [
|
|
17424
|
+
copyId,
|
|
17425
|
+
labelKey,
|
|
17426
|
+
BUTTON_COLLECTIONS_KEY,
|
|
17427
|
+
BUTTON_SNAPSHOTS_KEY,
|
|
17428
|
+
BUTTON_ASSIGNMENTS_KEY
|
|
17429
|
+
];
|
|
17430
|
+
if (sourceLabelKey) nodeKeys.push(sourceLabelKey);
|
|
17431
|
+
return {
|
|
17432
|
+
copy,
|
|
17433
|
+
content: nextContent,
|
|
17434
|
+
nodes: contentNodes(nextContent, nodeKeys)
|
|
17435
|
+
};
|
|
17436
|
+
}
|
|
17437
|
+
function listCollectionMembers(collection) {
|
|
17438
|
+
return Array.from(collection.querySelectorAll(CTA_BUTTON_SELECTOR)).map((el) => buttonId(el)).filter((id) => Boolean(id));
|
|
17439
|
+
}
|
|
17440
|
+
function contentNodes(content, keys) {
|
|
17441
|
+
return keys.filter((key) => content[key] !== void 0).map((key) => ({ key, text: content[key] }));
|
|
17442
|
+
}
|
|
17443
|
+
function deleteButton(source, content) {
|
|
17444
|
+
if (!canDeleteButton(source)) return null;
|
|
17445
|
+
const id = buttonId(source);
|
|
17446
|
+
if (!id) return null;
|
|
17447
|
+
const parent = source.parentElement;
|
|
17448
|
+
const nextSibling = source.nextSibling;
|
|
17449
|
+
const removed = source;
|
|
17450
|
+
const collection = buttonCollectionOf(source);
|
|
17451
|
+
const collectionId = collection?.getAttribute(COLLECTION_ATTR) ?? "";
|
|
17452
|
+
const previousCollections = readCollections(content);
|
|
17453
|
+
const previousHidden = readHiddenButtons(content);
|
|
17454
|
+
const snapshots = { ...readSnapshots(content) };
|
|
17455
|
+
const assignments = { ...readAssignments(content) };
|
|
17456
|
+
delete assignments[id];
|
|
17457
|
+
const remainingBeforeUnwrap = collection ? listCollectionMembers(collection).filter((member) => member !== id) : [];
|
|
17458
|
+
removed.remove();
|
|
17459
|
+
let nextCollections = { ...previousCollections };
|
|
17460
|
+
let unwrapped = null;
|
|
17461
|
+
if (collection && collectionId) {
|
|
17462
|
+
const members = listCollectionMembers(collection);
|
|
17463
|
+
if (members.length <= 1) {
|
|
17464
|
+
unwrapped = collection;
|
|
17465
|
+
unwrapCollection(collection);
|
|
17466
|
+
delete nextCollections[collectionId];
|
|
17467
|
+
} else {
|
|
17468
|
+
nextCollections[collectionId] = {
|
|
17469
|
+
id: collectionId,
|
|
17470
|
+
members,
|
|
17471
|
+
gap: collection.style.gap || previousCollections[collectionId]?.gap || "12px"
|
|
17472
|
+
};
|
|
17473
|
+
}
|
|
17474
|
+
}
|
|
17475
|
+
const hidden = previousHidden.includes(id) ? previousHidden : [...previousHidden, id];
|
|
17476
|
+
const nextContent = {
|
|
17477
|
+
...content,
|
|
17478
|
+
[id]: "",
|
|
17479
|
+
[BUTTON_COLLECTIONS_KEY]: JSON.stringify(nextCollections),
|
|
17480
|
+
[BUTTON_HIDDEN_KEY]: JSON.stringify(hidden),
|
|
17481
|
+
[BUTTON_SNAPSHOTS_KEY]: JSON.stringify(snapshots),
|
|
17482
|
+
[BUTTON_ASSIGNMENTS_KEY]: JSON.stringify(assignments)
|
|
17483
|
+
};
|
|
17484
|
+
return {
|
|
17485
|
+
content: nextContent,
|
|
17486
|
+
nodes: contentNodes(nextContent, [id, BUTTON_COLLECTIONS_KEY, BUTTON_HIDDEN_KEY, BUTTON_SNAPSHOTS_KEY, BUTTON_ASSIGNMENTS_KEY]),
|
|
17487
|
+
undo: () => {
|
|
17488
|
+
if (unwrapped && remainingBeforeUnwrap.length === 1) {
|
|
17489
|
+
const remaining = findButton(removed.ownerDocument, remainingBeforeUnwrap[0]);
|
|
17490
|
+
const host = remaining?.parentElement;
|
|
17491
|
+
if (remaining && host) {
|
|
17492
|
+
const restoredCollection = createCollection(
|
|
17493
|
+
removed.ownerDocument,
|
|
17494
|
+
collectionId,
|
|
17495
|
+
previousCollections[collectionId]?.gap || "12px"
|
|
17496
|
+
);
|
|
17497
|
+
host.insertBefore(restoredCollection, remaining);
|
|
17498
|
+
restoredCollection.append(remaining, removed);
|
|
17499
|
+
return;
|
|
17500
|
+
}
|
|
17501
|
+
}
|
|
17502
|
+
if (nextSibling && nextSibling.parentNode === parent) parent?.insertBefore(removed, nextSibling);
|
|
17503
|
+
else parent?.appendChild(removed);
|
|
17504
|
+
}
|
|
17505
|
+
};
|
|
17506
|
+
}
|
|
17507
|
+
function unwrapCollection(collection) {
|
|
17508
|
+
const parent = collection.parentElement;
|
|
17509
|
+
if (!parent) return;
|
|
17510
|
+
while (collection.firstChild) parent.insertBefore(collection.firstChild, collection);
|
|
17511
|
+
collection.remove();
|
|
17512
|
+
}
|
|
17513
|
+
function reorderButtonInCollection(button, clientX) {
|
|
17514
|
+
const collection = buttonCollectionOf(button);
|
|
17515
|
+
const id = buttonId(button);
|
|
17516
|
+
if (!collection || !id) return null;
|
|
17517
|
+
const siblings = Array.from(collection.querySelectorAll(CTA_BUTTON_SELECTOR)).filter((el) => el !== button);
|
|
17518
|
+
let placed = false;
|
|
17519
|
+
for (const sibling of siblings) {
|
|
17520
|
+
const rect = sibling.getBoundingClientRect();
|
|
17521
|
+
if (clientX < rect.left + rect.width / 2) {
|
|
17522
|
+
sibling.before(button);
|
|
17523
|
+
placed = true;
|
|
17524
|
+
break;
|
|
17525
|
+
}
|
|
17526
|
+
}
|
|
17527
|
+
if (!placed) collection.append(button);
|
|
17528
|
+
return listCollectionMembers(collection);
|
|
17529
|
+
}
|
|
17530
|
+
function listVisibleCollectionButtons(collection) {
|
|
17531
|
+
return Array.from(collection.querySelectorAll(CTA_BUTTON_SELECTOR)).filter((el) => {
|
|
17532
|
+
if (!buttonId(el)) return false;
|
|
17533
|
+
return el.getClientRects().length > 0;
|
|
17534
|
+
});
|
|
17535
|
+
}
|
|
17536
|
+
function isVerticalButtonLayout(items, collection) {
|
|
17537
|
+
if (items.length >= 2) {
|
|
17538
|
+
const a = items[0].getBoundingClientRect();
|
|
17539
|
+
const b = items[1].getBoundingClientRect();
|
|
17540
|
+
return b.top - a.bottom > b.left - a.right;
|
|
17541
|
+
}
|
|
17542
|
+
const style = window.getComputedStyle(collection);
|
|
17543
|
+
return style.flexDirection === "column" || style.flexDirection === "column-reverse";
|
|
17544
|
+
}
|
|
17545
|
+
function buildButtonCollectionDropSlots(collection) {
|
|
17546
|
+
const items = listVisibleCollectionButtons(collection);
|
|
17547
|
+
const barThickness = 3;
|
|
17548
|
+
const slots = [];
|
|
17549
|
+
if (items.length === 0) {
|
|
17550
|
+
const rect = collection.getBoundingClientRect();
|
|
17551
|
+
slots.push({
|
|
17552
|
+
insertIndex: 0,
|
|
17553
|
+
left: rect.left + rect.width / 2 - barThickness / 2,
|
|
17554
|
+
top: rect.top,
|
|
17555
|
+
width: barThickness,
|
|
17556
|
+
height: Math.max(rect.height, 24),
|
|
17557
|
+
direction: "vertical"
|
|
17558
|
+
});
|
|
17559
|
+
return slots;
|
|
17560
|
+
}
|
|
17561
|
+
if (isVerticalButtonLayout(items, collection)) {
|
|
17562
|
+
const edgeGap2 = items.length >= 2 ? Math.max(0, items[1].getBoundingClientRect().top - items[0].getBoundingClientRect().bottom) : 16;
|
|
17563
|
+
for (let i = 0; i <= items.length; i++) {
|
|
17564
|
+
let top;
|
|
17565
|
+
let left;
|
|
17566
|
+
let width;
|
|
17567
|
+
if (i === 0) {
|
|
17568
|
+
const first = items[0].getBoundingClientRect();
|
|
17569
|
+
top = first.top - edgeGap2 / 2 - barThickness / 2;
|
|
17570
|
+
left = first.left;
|
|
17571
|
+
width = first.width;
|
|
17572
|
+
} else if (i === items.length) {
|
|
17573
|
+
const last = items[items.length - 1].getBoundingClientRect();
|
|
17574
|
+
const lastGap = items.length >= 2 ? Math.max(0, last.top - items[items.length - 2].getBoundingClientRect().bottom) : edgeGap2;
|
|
17575
|
+
top = last.bottom + lastGap / 2 - barThickness / 2;
|
|
17576
|
+
left = last.left;
|
|
17577
|
+
width = last.width;
|
|
17578
|
+
} else {
|
|
17579
|
+
const prev = items[i - 1].getBoundingClientRect();
|
|
17580
|
+
const next = items[i].getBoundingClientRect();
|
|
17581
|
+
top = (prev.bottom + next.top) / 2 - barThickness / 2;
|
|
17582
|
+
left = Math.min(prev.left, next.left);
|
|
17583
|
+
width = Math.max(prev.right, next.right) - left;
|
|
17584
|
+
}
|
|
17585
|
+
slots.push({
|
|
17586
|
+
insertIndex: i,
|
|
17587
|
+
left,
|
|
17588
|
+
top,
|
|
17589
|
+
width: Math.max(width, 40),
|
|
17590
|
+
height: barThickness,
|
|
17591
|
+
direction: "horizontal"
|
|
17592
|
+
});
|
|
17593
|
+
}
|
|
17594
|
+
return slots;
|
|
17595
|
+
}
|
|
17596
|
+
const edgeGap = items.length >= 2 ? Math.max(0, items[1].getBoundingClientRect().left - items[0].getBoundingClientRect().right) : 12;
|
|
17597
|
+
for (let i = 0; i <= items.length; i++) {
|
|
17598
|
+
let left;
|
|
17599
|
+
let top;
|
|
17600
|
+
let height;
|
|
17601
|
+
if (i === 0) {
|
|
17602
|
+
const first = items[0].getBoundingClientRect();
|
|
17603
|
+
left = first.left - edgeGap / 2 - barThickness / 2;
|
|
17604
|
+
top = first.top;
|
|
17605
|
+
height = first.height;
|
|
17606
|
+
} else if (i === items.length) {
|
|
17607
|
+
const last = items[items.length - 1].getBoundingClientRect();
|
|
17608
|
+
const lastGap = items.length >= 2 ? Math.max(0, last.left - items[items.length - 2].getBoundingClientRect().right) : edgeGap;
|
|
17609
|
+
left = last.right + lastGap / 2 - barThickness / 2;
|
|
17610
|
+
top = last.top;
|
|
17611
|
+
height = last.height;
|
|
17612
|
+
} else {
|
|
17613
|
+
const prev = items[i - 1].getBoundingClientRect();
|
|
17614
|
+
const next = items[i].getBoundingClientRect();
|
|
17615
|
+
left = (prev.right + next.left) / 2 - barThickness / 2;
|
|
17616
|
+
top = Math.min(prev.top, next.top);
|
|
17617
|
+
height = Math.max(prev.bottom, next.bottom) - top;
|
|
17618
|
+
}
|
|
17619
|
+
slots.push({
|
|
17620
|
+
insertIndex: i,
|
|
17621
|
+
left,
|
|
17622
|
+
top,
|
|
17623
|
+
width: barThickness,
|
|
17624
|
+
height: Math.max(height, 24),
|
|
17625
|
+
direction: "vertical"
|
|
17626
|
+
});
|
|
17627
|
+
}
|
|
17628
|
+
return slots;
|
|
17629
|
+
}
|
|
17630
|
+
function hitTestButtonCollectionDropSlot(collection, clientX, clientY) {
|
|
17631
|
+
const slots = buildButtonCollectionDropSlots(collection);
|
|
17632
|
+
let best = null;
|
|
17633
|
+
for (const slot of slots) {
|
|
17634
|
+
const cx2 = slot.left + slot.width / 2;
|
|
17635
|
+
const cy = slot.top + slot.height / 2;
|
|
17636
|
+
const dist = slot.direction === "vertical" ? Math.abs(clientX - cx2) + Math.abs(clientY - cy) * 0.25 : Math.abs(clientY - cy) + Math.abs(clientX - cx2) * 0.25;
|
|
17637
|
+
if (!best || dist < best.dist) best = { slot, dist };
|
|
17638
|
+
}
|
|
17639
|
+
return best?.slot ?? null;
|
|
17640
|
+
}
|
|
17641
|
+
function insertButtonAtCollectionIndex(button, insertIndex) {
|
|
17642
|
+
const collection = buttonCollectionOf(button);
|
|
17643
|
+
if (!collection) return null;
|
|
17644
|
+
const items = listVisibleCollectionButtons(collection);
|
|
17645
|
+
const from = items.indexOf(button);
|
|
17646
|
+
if (from < 0) return null;
|
|
17647
|
+
const others = items.filter((el) => el !== button);
|
|
17648
|
+
let index = insertIndex;
|
|
17649
|
+
if (from < insertIndex) index -= 1;
|
|
17650
|
+
if (index <= 0) {
|
|
17651
|
+
const first = others[0];
|
|
17652
|
+
if (first) first.before(button);
|
|
17653
|
+
else collection.append(button);
|
|
17654
|
+
} else if (index >= others.length) {
|
|
17655
|
+
collection.append(button);
|
|
17656
|
+
} else {
|
|
17657
|
+
others[index].before(button);
|
|
17658
|
+
}
|
|
17659
|
+
return listCollectionMembers(collection);
|
|
17660
|
+
}
|
|
17661
|
+
function persistCollectionOrder(collection, content) {
|
|
17662
|
+
const id = collection.getAttribute(COLLECTION_ATTR);
|
|
17663
|
+
if (!id) return null;
|
|
17664
|
+
const collections = readCollections(content);
|
|
17665
|
+
const current = collections[id];
|
|
17666
|
+
const members = listCollectionMembers(collection);
|
|
17667
|
+
const next = {
|
|
17668
|
+
...collections,
|
|
17669
|
+
[id]: { id, members, gap: collection.style.gap || current?.gap || "12px" }
|
|
17670
|
+
};
|
|
17671
|
+
const nextContent = { ...content, [BUTTON_COLLECTIONS_KEY]: JSON.stringify(next) };
|
|
17672
|
+
return { content: nextContent, nodes: [{ key: BUTTON_COLLECTIONS_KEY, text: nextContent[BUTTON_COLLECTIONS_KEY] }] };
|
|
17673
|
+
}
|
|
17674
|
+
function hideButton(el) {
|
|
17675
|
+
if (el.getAttribute("data-ohw-button-hidden") === "") return;
|
|
17676
|
+
el.setAttribute("data-ohw-button-hidden", "");
|
|
17677
|
+
el.style.display = "none";
|
|
17678
|
+
}
|
|
17679
|
+
function syncButtonsFromContent(doc, content) {
|
|
17680
|
+
reconcileButtonCollections(doc, content);
|
|
17681
|
+
applyButtonContentFromContent(doc, content);
|
|
17682
|
+
applyButtonStylesFromContent(doc, content);
|
|
17683
|
+
}
|
|
17684
|
+
function applyButtonContentFromContent(doc, content) {
|
|
17685
|
+
const snapshots = readSnapshots(content);
|
|
17686
|
+
for (const snapshot of Object.values(snapshots)) {
|
|
17687
|
+
const el = findButton(doc, snapshot.id);
|
|
17688
|
+
if (!el) continue;
|
|
17689
|
+
applySnapshotContent(el, snapshot, content);
|
|
17690
|
+
}
|
|
17691
|
+
}
|
|
17692
|
+
function applySnapshotContent(el, snapshot, content) {
|
|
17693
|
+
const href = content[snapshot.id] ?? snapshot.href;
|
|
17694
|
+
if (href) el.setAttribute("href", href);
|
|
17695
|
+
const labelKey = snapshot.labelKey || labelKeyForHrefKey(snapshot.id);
|
|
17696
|
+
if (labelKey && !el.querySelector(`[data-ohw-key="${CSS.escape(labelKey)}"]`)) {
|
|
17697
|
+
const label2 = labelElement2(el);
|
|
17698
|
+
if (label2) label2.setAttribute("data-ohw-key", labelKey);
|
|
17699
|
+
}
|
|
17700
|
+
const text = content[labelKey];
|
|
17701
|
+
if (text === void 0) return;
|
|
17702
|
+
const label = labelElement2(el);
|
|
17703
|
+
if (label) {
|
|
17704
|
+
if (label.getAttribute("data-ohw-key") !== labelKey) label.setAttribute("data-ohw-key", labelKey);
|
|
17705
|
+
if (label.textContent !== text) label.textContent = text;
|
|
17706
|
+
}
|
|
17707
|
+
}
|
|
17708
|
+
function reconcileButtonCollections(doc, content) {
|
|
17709
|
+
const hidden = new Set(readHiddenButtons(content));
|
|
17710
|
+
for (const id of hidden) {
|
|
17711
|
+
const el = findButton(doc, id);
|
|
17712
|
+
if (el) hideButton(el);
|
|
17713
|
+
}
|
|
17714
|
+
const snapshots = readSnapshots(content);
|
|
17715
|
+
const collections = readCollections(content);
|
|
17716
|
+
for (const collectionState of Object.values(collections)) {
|
|
17717
|
+
const live = collectionState.members.map((id) => findButton(doc, id) ?? restoreSnapshot(doc, snapshots[id], content)).filter((el) => Boolean(el && !hidden.has(buttonId(el) ?? "")));
|
|
17718
|
+
if (live.length === 0) continue;
|
|
17719
|
+
if (live.length === 1) {
|
|
17720
|
+
const existing = buttonCollectionOf(live[0]);
|
|
17721
|
+
if (existing) unwrapCollection(existing);
|
|
17722
|
+
continue;
|
|
17723
|
+
}
|
|
17724
|
+
const anchor = live.find((el) => el.isConnected) ?? live[0];
|
|
17725
|
+
let collection = live.map((el) => buttonCollectionOf(el)).find((el) => el?.getAttribute(COLLECTION_ATTR) === collectionState.id) ?? null;
|
|
17726
|
+
if (!collection) {
|
|
17727
|
+
if (!anchor.parentElement) continue;
|
|
17728
|
+
collection = createCollection(doc, collectionState.id, collectionState.gap);
|
|
17729
|
+
anchor.parentElement.insertBefore(collection, anchor);
|
|
17730
|
+
}
|
|
17731
|
+
styleCollection(collection, collectionState.gap);
|
|
17732
|
+
const current = listCollectionMembers(collection);
|
|
17733
|
+
const sameOrder = current.length === live.length && current.every((id, index) => id === buttonId(live[index]));
|
|
17734
|
+
if (!sameOrder) {
|
|
17735
|
+
for (const member of live) collection.append(member);
|
|
17736
|
+
}
|
|
17737
|
+
for (const member of live) setButtonDragAttr(member);
|
|
17738
|
+
}
|
|
17739
|
+
}
|
|
17740
|
+
function restoreSnapshot(doc, snapshot, content) {
|
|
17741
|
+
if (!snapshot) return null;
|
|
17742
|
+
const existing = findButton(doc, snapshot.id);
|
|
17743
|
+
if (existing) {
|
|
17744
|
+
applySnapshotContent(existing, snapshot, content);
|
|
17745
|
+
return existing;
|
|
17746
|
+
}
|
|
17747
|
+
const el = htmlToElement(doc, snapshot.html);
|
|
17748
|
+
if (!el) return null;
|
|
17749
|
+
el.setAttribute("data-ohw-href-key", snapshot.id);
|
|
17750
|
+
const label = labelElement2(el);
|
|
17751
|
+
const labelKey = snapshot.labelKey || labelKeyForHrefKey(snapshot.id);
|
|
17752
|
+
if (label) label.setAttribute("data-ohw-key", labelKey);
|
|
17753
|
+
applySnapshotContent(el, snapshot, content);
|
|
17754
|
+
setButtonDragAttr(el);
|
|
17755
|
+
return el;
|
|
17756
|
+
}
|
|
17757
|
+
function navbarCtasInScope(el) {
|
|
17758
|
+
const scope = el.closest("nav, [data-ohw-nav-root], [data-ohw-nav-drawer]") ?? el.parentElement;
|
|
17759
|
+
if (!scope) return [];
|
|
17760
|
+
return Array.from(scope.querySelectorAll(CTA_BUTTON_SELECTOR)).filter(
|
|
17761
|
+
(button) => isNavbarCta(button) && buttonId(button)
|
|
17762
|
+
);
|
|
17763
|
+
}
|
|
17764
|
+
function ensureNavbarButtonCollection(button, content) {
|
|
17765
|
+
const existing = buttonCollectionOf(button);
|
|
17766
|
+
if (existing) return existing;
|
|
17767
|
+
if (!isNavbarCta(button) || !buttonId(button)) return null;
|
|
17768
|
+
const parent = button.parentElement;
|
|
17769
|
+
if (!parent) return null;
|
|
17770
|
+
const siblings = navbarCtasInScope(button).filter((el) => el.parentElement === parent);
|
|
17771
|
+
if (siblings.length < 2) return null;
|
|
17772
|
+
const id = nextCollectionId(content, button.ownerDocument);
|
|
17773
|
+
const collection = createCollection(button.ownerDocument, id, collectionGap(button, tokensFromButton(button)));
|
|
17774
|
+
siblings[0].before(collection);
|
|
17775
|
+
for (const member of siblings) {
|
|
17776
|
+
collection.append(member);
|
|
17777
|
+
setButtonDragAttr(member);
|
|
17778
|
+
}
|
|
17779
|
+
return collection;
|
|
17780
|
+
}
|
|
17781
|
+
function collectionDragEnabled(el) {
|
|
17782
|
+
if (!isNavbarCta(el) || !buttonId(el)) return false;
|
|
17783
|
+
if (buttonCollectionOf(el)) return true;
|
|
17784
|
+
return navbarCtasInScope(el).length >= 2;
|
|
17785
|
+
}
|
|
17786
|
+
|
|
17787
|
+
// src/lib/item-drag-interaction.ts
|
|
17788
|
+
function disableNativeHrefDrag(el) {
|
|
17789
|
+
if (el.draggable) el.draggable = false;
|
|
17790
|
+
if (el.getAttribute("draggable") !== "false") {
|
|
17791
|
+
el.setAttribute("draggable", "false");
|
|
17792
|
+
}
|
|
17793
|
+
}
|
|
17794
|
+
function clearTextSelection() {
|
|
17795
|
+
const sel = window.getSelection();
|
|
17796
|
+
if (sel && !sel.isCollapsed) sel.removeAllRanges();
|
|
17797
|
+
}
|
|
17798
|
+
function armItemPressDrag() {
|
|
17799
|
+
document.documentElement.setAttribute("data-ohw-footer-press-drag", "");
|
|
17800
|
+
}
|
|
17801
|
+
function lockItemDuringDrag() {
|
|
17802
|
+
document.documentElement.removeAttribute("data-ohw-footer-press-drag");
|
|
17803
|
+
document.documentElement.setAttribute("data-ohw-item-dragging", "");
|
|
17804
|
+
clearTextSelection();
|
|
17805
|
+
}
|
|
17806
|
+
function unlockItemDragInteraction() {
|
|
17807
|
+
const wasDragging = document.documentElement.hasAttribute("data-ohw-item-dragging");
|
|
17808
|
+
document.documentElement.removeAttribute("data-ohw-footer-press-drag");
|
|
17809
|
+
document.documentElement.removeAttribute("data-ohw-item-dragging");
|
|
17810
|
+
if (wasDragging) clearTextSelection();
|
|
17811
|
+
}
|
|
17812
|
+
var armFooterPressDrag = armItemPressDrag;
|
|
17813
|
+
var lockFooterDuringDrag = lockItemDuringDrag;
|
|
17814
|
+
var unlockFooterDragInteraction = unlockItemDragInteraction;
|
|
17815
|
+
|
|
17816
|
+
// src/lib/nav-dnd.ts
|
|
17817
|
+
function listReorderableNavItems(draggedEl) {
|
|
17818
|
+
return listActiveNavbarItems(draggedEl).filter((el) => {
|
|
17819
|
+
const key = el.getAttribute("data-ohw-href-key");
|
|
17820
|
+
return isNavbarHrefKey(key) && !isNestedNavChild(el);
|
|
17821
|
+
});
|
|
17822
|
+
}
|
|
17823
|
+
function resolveParentNavHrefKey(child) {
|
|
17824
|
+
const childrenRoot = child.closest("[data-ohw-nav-children]");
|
|
17825
|
+
const group = childrenRoot?.closest("[data-ohw-nav-group]");
|
|
17826
|
+
if (!group) return null;
|
|
17827
|
+
const trigger = group.querySelector(":scope > [data-ohw-href-key]") ?? Array.from(group.querySelectorAll("[data-ohw-href-key]")).find(
|
|
17828
|
+
(el) => !el.closest("[data-ohw-nav-children]")
|
|
17829
|
+
) ?? null;
|
|
17830
|
+
const key = trigger?.getAttribute("data-ohw-href-key");
|
|
17831
|
+
return key && isNavbarHrefKey(key) ? key : null;
|
|
17832
|
+
}
|
|
17833
|
+
function listNavChildren(parentHrefKey, draggedEl) {
|
|
17834
|
+
const items = listActiveNavbarItems(draggedEl);
|
|
17835
|
+
const parent = items.find((el) => el.getAttribute("data-ohw-href-key") === parentHrefKey);
|
|
17836
|
+
if (!parent) return [];
|
|
17837
|
+
const group = parent.closest("[data-ohw-nav-group]");
|
|
17838
|
+
const childrenRoot = group?.querySelector(":scope > [data-ohw-nav-children]");
|
|
17839
|
+
if (!childrenRoot) return [];
|
|
17840
|
+
return Array.from(childrenRoot.querySelectorAll(":scope > [data-ohw-href-key]")).filter(
|
|
17841
|
+
(el) => isNavbarHrefKey(el.getAttribute("data-ohw-href-key"))
|
|
17842
|
+
);
|
|
17843
|
+
}
|
|
17844
|
+
function isVerticalNavLayout(items, draggedEl) {
|
|
17845
|
+
const visible = items.filter((el) => el.getClientRects().length > 0);
|
|
17846
|
+
if (visible.length >= 2) {
|
|
17847
|
+
const a = visible[0].getBoundingClientRect();
|
|
17848
|
+
const b = visible[1].getBoundingClientRect();
|
|
17849
|
+
const verticalGap = b.top - a.bottom;
|
|
17850
|
+
const horizontalGap = b.left - a.right;
|
|
17851
|
+
return verticalGap > horizontalGap;
|
|
17852
|
+
}
|
|
17853
|
+
const container = getActiveNavbarListContainer(draggedEl);
|
|
17854
|
+
if (!container) return false;
|
|
17855
|
+
const style = window.getComputedStyle(container);
|
|
17856
|
+
return style.flexDirection === "column" || style.flexDirection === "column-reverse";
|
|
17857
|
+
}
|
|
17858
|
+
function buildVerticalRootNavDropSlots(items, draggedEl) {
|
|
17859
|
+
const slots = [];
|
|
17860
|
+
const barThickness = 3;
|
|
17861
|
+
if (items.length === 0) {
|
|
17862
|
+
const container = getActiveNavbarListContainer(draggedEl);
|
|
17863
|
+
if (!container) return slots;
|
|
17864
|
+
const rect = container.getBoundingClientRect();
|
|
17865
|
+
slots.push({
|
|
17866
|
+
insertIndex: 0,
|
|
17867
|
+
parentId: null,
|
|
17868
|
+
left: rect.left,
|
|
17869
|
+
top: rect.top + rect.height / 2 - barThickness / 2,
|
|
17870
|
+
width: Math.max(rect.width, 40),
|
|
17871
|
+
height: barThickness,
|
|
17872
|
+
direction: "horizontal"
|
|
17873
|
+
});
|
|
17874
|
+
return slots;
|
|
17875
|
+
}
|
|
17876
|
+
const edgeGap = (() => {
|
|
17877
|
+
if (items.length < 2) return 16;
|
|
17878
|
+
const a = items[0].getBoundingClientRect();
|
|
17879
|
+
const b = items[1].getBoundingClientRect();
|
|
17880
|
+
return Math.max(0, b.top - a.bottom);
|
|
17881
|
+
})();
|
|
17882
|
+
for (let i = 0; i <= items.length; i++) {
|
|
17883
|
+
let top;
|
|
17884
|
+
let width;
|
|
17885
|
+
let left;
|
|
17886
|
+
if (i === 0) {
|
|
17887
|
+
const first = items[0].getBoundingClientRect();
|
|
17888
|
+
top = first.top - edgeGap / 2 - barThickness / 2;
|
|
17889
|
+
left = first.left;
|
|
17890
|
+
width = first.width;
|
|
17891
|
+
} else if (i === items.length) {
|
|
17892
|
+
const last = items[items.length - 1].getBoundingClientRect();
|
|
17893
|
+
const lastGap = items.length >= 2 ? Math.max(0, last.top - items[items.length - 2].getBoundingClientRect().bottom) : edgeGap;
|
|
17894
|
+
top = last.bottom + lastGap / 2 - barThickness / 2;
|
|
17895
|
+
left = last.left;
|
|
17896
|
+
width = last.width;
|
|
17897
|
+
} else {
|
|
17898
|
+
const prev = items[i - 1].getBoundingClientRect();
|
|
17899
|
+
const next = items[i].getBoundingClientRect();
|
|
17900
|
+
top = (prev.bottom + next.top) / 2 - barThickness / 2;
|
|
17901
|
+
left = Math.min(prev.left, next.left);
|
|
17902
|
+
width = Math.max(prev.right, next.right) - left;
|
|
16111
17903
|
}
|
|
16112
17904
|
slots.push({
|
|
16113
17905
|
insertIndex: i,
|
|
@@ -16421,7 +18213,7 @@ function useNavItemDrag({
|
|
|
16421
18213
|
document.querySelectorAll(
|
|
16422
18214
|
"nav [data-ohw-href-key], [data-ohw-nav-container] [data-ohw-href-key], [data-ohw-nav-drawer] [data-ohw-href-key]"
|
|
16423
18215
|
).forEach((el) => {
|
|
16424
|
-
if (isNavbarHrefKey(el.getAttribute("data-ohw-href-key"))) {
|
|
18216
|
+
if (isNavbarHrefKey(el.getAttribute("data-ohw-href-key")) || isCtaButton(el)) {
|
|
16425
18217
|
disableNativeHrefDrag(el);
|
|
16426
18218
|
}
|
|
16427
18219
|
});
|
|
@@ -16730,12 +18522,6 @@ var SECTION_DRAG_EXCLUDED_SELECTOR = [
|
|
|
16730
18522
|
"[data-ohw-media-overlay]",
|
|
16731
18523
|
"[data-ohw-media-skeleton]"
|
|
16732
18524
|
].join(", ");
|
|
16733
|
-
function visibleClip(ps) {
|
|
16734
|
-
if (!ps) return null;
|
|
16735
|
-
const top = Math.max(0, ps.headerH - ps.iframeOffsetTop);
|
|
16736
|
-
const bottom = Math.min(window.innerHeight, ps.headerH + ps.canvasH - ps.iframeOffsetTop);
|
|
16737
|
-
return { top, bottom: Math.max(top, bottom) };
|
|
16738
|
-
}
|
|
16739
18525
|
function useSectionDrag({
|
|
16740
18526
|
isEditMode,
|
|
16741
18527
|
editContentRef,
|
|
@@ -16772,7 +18558,7 @@ function useSectionDrag({
|
|
|
16772
18558
|
}, [postToParentRef, stopAutoScroll]);
|
|
16773
18559
|
const updateAutoScroll = useCallback9(
|
|
16774
18560
|
(clientY) => {
|
|
16775
|
-
const clip =
|
|
18561
|
+
const clip = getIframeChromeClip(parentScrollRef.current);
|
|
16776
18562
|
let delta = 0;
|
|
16777
18563
|
if (clip) {
|
|
16778
18564
|
const distTop = clientY - clip.top;
|
|
@@ -16979,7 +18765,7 @@ function useSectionDrag({
|
|
|
16979
18765
|
|
|
16980
18766
|
// src/ui/footer-container-chrome.tsx
|
|
16981
18767
|
import { Plus as Plus2 } from "lucide-react";
|
|
16982
|
-
import { jsx as
|
|
18768
|
+
import { jsx as jsx32, jsxs as jsxs22 } from "react/jsx-runtime";
|
|
16983
18769
|
function FooterContainerChrome({
|
|
16984
18770
|
rect,
|
|
16985
18771
|
onAdd,
|
|
@@ -16987,7 +18773,7 @@ function FooterContainerChrome({
|
|
|
16987
18773
|
}) {
|
|
16988
18774
|
const chromeGap = 6;
|
|
16989
18775
|
const buttonMargin = 7;
|
|
16990
|
-
return /* @__PURE__ */
|
|
18776
|
+
return /* @__PURE__ */ jsx32(TooltipProvider, { delayDuration: 0, children: /* @__PURE__ */ jsx32(
|
|
16991
18777
|
"div",
|
|
16992
18778
|
{
|
|
16993
18779
|
"data-ohw-footer-container-chrome": "",
|
|
@@ -16999,8 +18785,8 @@ function FooterContainerChrome({
|
|
|
16999
18785
|
width: rect.width + chromeGap * 2,
|
|
17000
18786
|
height: rect.height + chromeGap * 2
|
|
17001
18787
|
},
|
|
17002
|
-
children: /* @__PURE__ */
|
|
17003
|
-
/* @__PURE__ */
|
|
18788
|
+
children: /* @__PURE__ */ jsxs22(Tooltip, { children: [
|
|
18789
|
+
/* @__PURE__ */ jsx32(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsx32(
|
|
17004
18790
|
"button",
|
|
17005
18791
|
{
|
|
17006
18792
|
type: "button",
|
|
@@ -17019,10 +18805,10 @@ function FooterContainerChrome({
|
|
|
17019
18805
|
if (addDisabled) return;
|
|
17020
18806
|
onAdd();
|
|
17021
18807
|
},
|
|
17022
|
-
children: /* @__PURE__ */
|
|
18808
|
+
children: /* @__PURE__ */ jsx32(Plus2, { className: "size-4 shrink-0 text-foreground", "aria-hidden": true })
|
|
17023
18809
|
}
|
|
17024
18810
|
) }),
|
|
17025
|
-
/* @__PURE__ */
|
|
18811
|
+
/* @__PURE__ */ jsx32(TooltipContent, { side: "bottom", sideOffset: 9, children: addDisabled ? "Maximum columns reached" : "Add item" })
|
|
17026
18812
|
] })
|
|
17027
18813
|
}
|
|
17028
18814
|
) });
|
|
@@ -17184,7 +18970,14 @@ function collectEditableNodes(extraContent, root = document) {
|
|
|
17184
18970
|
// so collecting the DOM alone left them behind: the draft knew the row was showing icons and
|
|
17185
18971
|
// had gained an item, and the published page went back to the template's own (OHH-736).
|
|
17186
18972
|
SOCIALS_ORDER_KEY,
|
|
17187
|
-
SOCIALS_DISPLAY_KEY
|
|
18973
|
+
SOCIALS_DISPLAY_KEY,
|
|
18974
|
+
// Button variant/size tokens and per-CTA assignments — JSON in editContent, applied on hydrate.
|
|
18975
|
+
BUTTON_VARIANTS_KEY,
|
|
18976
|
+
BUTTON_SIZES_KEY,
|
|
18977
|
+
BUTTON_ASSIGNMENTS_KEY,
|
|
18978
|
+
BUTTON_COLLECTIONS_KEY,
|
|
18979
|
+
BUTTON_SNAPSHOTS_KEY,
|
|
18980
|
+
BUTTON_HIDDEN_KEY
|
|
17188
18981
|
]) {
|
|
17189
18982
|
const text = extraContent[key];
|
|
17190
18983
|
if (typeof text === "string" && text.length > 0) {
|
|
@@ -17505,13 +19298,13 @@ function deleteSelectedNavFooterItem(deps) {
|
|
|
17505
19298
|
|
|
17506
19299
|
// src/ui/navbar-container-chrome.tsx
|
|
17507
19300
|
import { Plus as Plus3 } from "lucide-react";
|
|
17508
|
-
import { jsx as
|
|
19301
|
+
import { jsx as jsx33 } from "react/jsx-runtime";
|
|
17509
19302
|
function NavbarContainerChrome({
|
|
17510
19303
|
rect,
|
|
17511
19304
|
onAdd
|
|
17512
19305
|
}) {
|
|
17513
19306
|
const chromeGap = 6;
|
|
17514
|
-
return /* @__PURE__ */
|
|
19307
|
+
return /* @__PURE__ */ jsx33(
|
|
17515
19308
|
"div",
|
|
17516
19309
|
{
|
|
17517
19310
|
"data-ohw-navbar-container-chrome": "",
|
|
@@ -17523,7 +19316,7 @@ function NavbarContainerChrome({
|
|
|
17523
19316
|
width: rect.width + chromeGap * 2,
|
|
17524
19317
|
height: rect.height + chromeGap * 2
|
|
17525
19318
|
},
|
|
17526
|
-
children: /* @__PURE__ */
|
|
19319
|
+
children: /* @__PURE__ */ jsx33(
|
|
17527
19320
|
"button",
|
|
17528
19321
|
{
|
|
17529
19322
|
type: "button",
|
|
@@ -17540,7 +19333,7 @@ function NavbarContainerChrome({
|
|
|
17540
19333
|
e.stopPropagation();
|
|
17541
19334
|
onAdd();
|
|
17542
19335
|
},
|
|
17543
|
-
children: /* @__PURE__ */
|
|
19336
|
+
children: /* @__PURE__ */ jsx33(Plus3, { className: "size-4 shrink-0 text-foreground", "aria-hidden": true })
|
|
17544
19337
|
}
|
|
17545
19338
|
)
|
|
17546
19339
|
}
|
|
@@ -17549,7 +19342,7 @@ function NavbarContainerChrome({
|
|
|
17549
19342
|
|
|
17550
19343
|
// src/ui/drop-indicator.tsx
|
|
17551
19344
|
import * as React11 from "react";
|
|
17552
|
-
import { jsx as
|
|
19345
|
+
import { jsx as jsx34 } from "react/jsx-runtime";
|
|
17553
19346
|
var dropIndicatorVariants = cva(
|
|
17554
19347
|
"ov-gap-line pointer-events-none shrink-0 transition-opacity duration-150",
|
|
17555
19348
|
{
|
|
@@ -17573,7 +19366,7 @@ var dropIndicatorVariants = cva(
|
|
|
17573
19366
|
);
|
|
17574
19367
|
var DropIndicator = React11.forwardRef(
|
|
17575
19368
|
({ className, direction, state, ...props }, ref) => {
|
|
17576
|
-
return /* @__PURE__ */
|
|
19369
|
+
return /* @__PURE__ */ jsx34(
|
|
17577
19370
|
"div",
|
|
17578
19371
|
{
|
|
17579
19372
|
ref,
|
|
@@ -17590,7 +19383,7 @@ var DropIndicator = React11.forwardRef(
|
|
|
17590
19383
|
DropIndicator.displayName = "DropIndicator";
|
|
17591
19384
|
|
|
17592
19385
|
// src/ui/badge.tsx
|
|
17593
|
-
import { jsx as
|
|
19386
|
+
import { jsx as jsx35 } from "react/jsx-runtime";
|
|
17594
19387
|
var badgeVariants = cva(
|
|
17595
19388
|
"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",
|
|
17596
19389
|
{
|
|
@@ -17608,12 +19401,12 @@ var badgeVariants = cva(
|
|
|
17608
19401
|
}
|
|
17609
19402
|
);
|
|
17610
19403
|
function Badge({ className, variant, ...props }) {
|
|
17611
|
-
return /* @__PURE__ */
|
|
19404
|
+
return /* @__PURE__ */ jsx35("div", { className: cn(badgeVariants({ variant }), className), ...props });
|
|
17612
19405
|
}
|
|
17613
19406
|
|
|
17614
19407
|
// src/OhhwellsBridge.tsx
|
|
17615
|
-
import { Link as Link2, Plus as Plus4, Settings } from "lucide-react";
|
|
17616
|
-
import { Fragment as Fragment10, jsx as
|
|
19408
|
+
import { Brush as Brush2, Link as Link2, Plus as Plus4, Settings } from "lucide-react";
|
|
19409
|
+
import { Fragment as Fragment10, jsx as jsx36, jsxs as jsxs23 } from "react/jsx-runtime";
|
|
17617
19410
|
var PRIMARY5 = "#0885FE";
|
|
17618
19411
|
var IMAGE_FADE_MS = 300;
|
|
17619
19412
|
var MEDIA_SETTLE_TIMEOUT_MS = 2500;
|
|
@@ -17735,7 +19528,7 @@ function duplicateSchedulingWidget(instanceId, scheduleId) {
|
|
|
17735
19528
|
schedulingRoots.set(container, root);
|
|
17736
19529
|
flushSync2(() => {
|
|
17737
19530
|
root.render(
|
|
17738
|
-
/* @__PURE__ */
|
|
19531
|
+
/* @__PURE__ */ jsx36(
|
|
17739
19532
|
SchedulingWidget,
|
|
17740
19533
|
{
|
|
17741
19534
|
notifyOnConnect: false,
|
|
@@ -17778,21 +19571,10 @@ function parseSchedulingInsertAfter(insertAfter) {
|
|
|
17778
19571
|
insertBefore: insertAfter.slice(idx + INSERT_BEFORE_MARKER.length)
|
|
17779
19572
|
};
|
|
17780
19573
|
}
|
|
17781
|
-
function
|
|
17782
|
-
|
|
17783
|
-
const
|
|
17784
|
-
|
|
17785
|
-
return { effectiveInsertAfter, insertBefore };
|
|
17786
|
-
}
|
|
17787
|
-
function getSchedulingMountPoint(insertAfter) {
|
|
17788
|
-
const { anchor } = parseSchedulingInsertAfter(insertAfter);
|
|
17789
|
-
let anchorEl = document.querySelector(`[data-ohw-section="${anchor}"]`);
|
|
17790
|
-
if (!anchorEl && anchor === "scheduling") {
|
|
17791
|
-
const widgets = Array.from(document.querySelectorAll('[data-ohw-section^="scheduling-"]'));
|
|
17792
|
-
anchorEl = widgets.at(-1) ?? null;
|
|
17793
|
-
}
|
|
17794
|
-
if (!anchorEl) return null;
|
|
17795
|
-
return anchorEl.closest('[data-ohw-section-container="scheduling"]') ?? anchorEl;
|
|
19574
|
+
function resolveEntryAnchor(entry) {
|
|
19575
|
+
if (entry.anchorId !== void 0) return { anchorId: entry.anchorId, beforeId: entry.beforeId ?? null };
|
|
19576
|
+
const parsed = parseSchedulingInsertAfter(entry.insertAfter);
|
|
19577
|
+
return { anchorId: parsed.anchor, beforeId: parsed.insertBefore };
|
|
17796
19578
|
}
|
|
17797
19579
|
function schedulingMountDepth(insertAfter) {
|
|
17798
19580
|
if (!insertAfter.includes(INSERT_BEFORE_MARKER)) return 0;
|
|
@@ -17809,8 +19591,7 @@ function getPageSchedulingEntries(raw) {
|
|
|
17809
19591
|
}
|
|
17810
19592
|
}
|
|
17811
19593
|
function isSchedulingWidgetMissing(entry) {
|
|
17812
|
-
|
|
17813
|
-
return !document.querySelector(`[data-ohw-section="${schedulingSectionId(effectiveInsertAfter)}"]`);
|
|
19594
|
+
return !document.querySelector(`[data-ohw-section="${schedulingSectionId(entry.insertAfter)}"]`);
|
|
17814
19595
|
}
|
|
17815
19596
|
function hasMissingSchedulingWidgets(entries) {
|
|
17816
19597
|
return entries.some(isSchedulingWidgetMissing);
|
|
@@ -17848,17 +19629,18 @@ function initSectionsFromContent(content, removeExisting = false, currentPath =
|
|
|
17848
19629
|
} catch {
|
|
17849
19630
|
}
|
|
17850
19631
|
}
|
|
17851
|
-
function mountSchedulingWidget(
|
|
17852
|
-
const
|
|
17853
|
-
const sectionId = schedulingSectionId(
|
|
19632
|
+
function mountSchedulingWidget(anchorId, notifyOnConnect = false, scheduleId, beforeId, existingWidgetId) {
|
|
19633
|
+
const widgetId = existingWidgetId ?? (beforeId ? `${anchorId}${INSERT_BEFORE_MARKER}${beforeId}` : anchorId);
|
|
19634
|
+
const sectionId = schedulingSectionId(widgetId);
|
|
17854
19635
|
if (document.querySelector(`[data-ohw-section="${sectionId}"]`)) return false;
|
|
17855
|
-
const
|
|
17856
|
-
if (!
|
|
19636
|
+
const anchorEl = document.querySelector(`[data-ohw-section="${anchorId}"]`);
|
|
19637
|
+
if (!anchorEl) return false;
|
|
19638
|
+
const mountPoint = anchorEl.closest('[data-ohw-section-container="scheduling"]') ?? anchorEl;
|
|
17857
19639
|
const container = document.createElement("div");
|
|
17858
19640
|
container.dataset.ohwSectionContainer = "scheduling";
|
|
17859
19641
|
container.dataset.ohwInstance = sectionId;
|
|
17860
|
-
if (
|
|
17861
|
-
const beforeAnchor = document.querySelector(`[data-ohw-section="${
|
|
19642
|
+
if (beforeId) {
|
|
19643
|
+
const beforeAnchor = document.querySelector(`[data-ohw-section="${beforeId}"]`);
|
|
17862
19644
|
const beforePoint = beforeAnchor?.closest('[data-ohw-section-container="scheduling"]') ?? beforeAnchor;
|
|
17863
19645
|
if (!beforePoint) return false;
|
|
17864
19646
|
beforePoint.insertAdjacentElement("beforebegin", container);
|
|
@@ -17869,20 +19651,26 @@ function mountSchedulingWidget(insertAfter, notifyOnConnect = false, scheduleId,
|
|
|
17869
19651
|
}
|
|
17870
19652
|
tail.insertAdjacentElement("afterend", container);
|
|
17871
19653
|
}
|
|
17872
|
-
|
|
17873
|
-
|
|
17874
|
-
|
|
17875
|
-
|
|
17876
|
-
|
|
17877
|
-
|
|
17878
|
-
|
|
17879
|
-
|
|
17880
|
-
|
|
17881
|
-
|
|
17882
|
-
|
|
17883
|
-
|
|
17884
|
-
|
|
17885
|
-
|
|
19654
|
+
try {
|
|
19655
|
+
const root = createRoot2(container);
|
|
19656
|
+
schedulingRoots.set(container, root);
|
|
19657
|
+
flushSync2(() => {
|
|
19658
|
+
root.render(
|
|
19659
|
+
/* @__PURE__ */ jsx36(
|
|
19660
|
+
SchedulingWidget,
|
|
19661
|
+
{
|
|
19662
|
+
notifyOnConnect,
|
|
19663
|
+
initialScheduleId: scheduleId,
|
|
19664
|
+
insertAfter: widgetId
|
|
19665
|
+
}
|
|
19666
|
+
)
|
|
19667
|
+
);
|
|
19668
|
+
});
|
|
19669
|
+
} catch (err) {
|
|
19670
|
+
console.error("[ow:scheduling] render threw", err);
|
|
19671
|
+
container.remove();
|
|
19672
|
+
return false;
|
|
19673
|
+
}
|
|
17886
19674
|
const tracker = getSectionsTracker();
|
|
17887
19675
|
let sections = [];
|
|
17888
19676
|
try {
|
|
@@ -17890,10 +19678,12 @@ function mountSchedulingWidget(insertAfter, notifyOnConnect = false, scheduleId,
|
|
|
17890
19678
|
} catch {
|
|
17891
19679
|
}
|
|
17892
19680
|
const inEditor = typeof window !== "undefined" && window.self !== window.top;
|
|
17893
|
-
if (inEditor && !sections.find((s) => s.type === "scheduling" && s.insertAfter ===
|
|
19681
|
+
if (inEditor && !sections.find((s) => s.type === "scheduling" && s.insertAfter === widgetId)) {
|
|
17894
19682
|
sections.push({
|
|
17895
19683
|
type: "scheduling",
|
|
17896
|
-
insertAfter:
|
|
19684
|
+
insertAfter: widgetId,
|
|
19685
|
+
anchorId,
|
|
19686
|
+
beforeId: beforeId ?? null,
|
|
17897
19687
|
pagePath: window.location.pathname,
|
|
17898
19688
|
...scheduleId ? { scheduleId } : {}
|
|
17899
19689
|
});
|
|
@@ -17907,7 +19697,8 @@ function mountSchedulingEntries(entries, notifyOnConnect = false) {
|
|
|
17907
19697
|
for (let i = pending.length - 1; i >= 0; i--) {
|
|
17908
19698
|
const entry = pending[i];
|
|
17909
19699
|
const shouldNotify = typeof notifyOnConnect === "function" ? notifyOnConnect(entry) : notifyOnConnect;
|
|
17910
|
-
|
|
19700
|
+
const { anchorId, beforeId } = resolveEntryAnchor(entry);
|
|
19701
|
+
if (mountSchedulingWidget(anchorId, shouldNotify, entry.scheduleId ?? null, beforeId, entry.insertAfter)) {
|
|
17911
19702
|
pending.splice(i, 1);
|
|
17912
19703
|
}
|
|
17913
19704
|
}
|
|
@@ -18036,8 +19827,8 @@ function lockVideoBox(video) {
|
|
|
18036
19827
|
}
|
|
18037
19828
|
const fit = video.style.objectFit || getComputedStyle(video).objectFit;
|
|
18038
19829
|
const bg = getComputedStyle(video).backgroundColor;
|
|
18039
|
-
const
|
|
18040
|
-
if (fit === "contain" &&
|
|
19830
|
+
const isTransparent2 = bg === "rgba(0, 0, 0, 0)" || bg === "transparent" || !bg;
|
|
19831
|
+
if (fit === "contain" && isTransparent2) {
|
|
18041
19832
|
video.style.backgroundColor = "var(--color-dark, #000)";
|
|
18042
19833
|
}
|
|
18043
19834
|
}
|
|
@@ -18084,6 +19875,11 @@ function applyLinkByKey(key, val) {
|
|
|
18084
19875
|
hrefAnchors.forEach((el) => applyLinkHref(el, val));
|
|
18085
19876
|
}
|
|
18086
19877
|
}
|
|
19878
|
+
function isInsideLinkEditor(target) {
|
|
19879
|
+
return Boolean(
|
|
19880
|
+
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"]')
|
|
19881
|
+
);
|
|
19882
|
+
}
|
|
18087
19883
|
function isInsideFloatingPanel(target) {
|
|
18088
19884
|
return Boolean(target.closest("[data-ohw-floating-panel]"));
|
|
18089
19885
|
}
|
|
@@ -18091,11 +19887,6 @@ function isPointOverFloatingPanel(clientX, clientY) {
|
|
|
18091
19887
|
const el = document.elementFromPoint(clientX, clientY);
|
|
18092
19888
|
return Boolean(el instanceof Element && el.closest("[data-ohw-floating-panel]"));
|
|
18093
19889
|
}
|
|
18094
|
-
function isInsideLinkEditor(target) {
|
|
18095
|
-
return Boolean(
|
|
18096
|
-
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"]')
|
|
18097
|
-
);
|
|
18098
|
-
}
|
|
18099
19890
|
function getHrefKeyFromElement(el) {
|
|
18100
19891
|
if (!el) return null;
|
|
18101
19892
|
const anchor = el.closest("[data-ohw-href-key]");
|
|
@@ -18187,7 +19978,10 @@ function listNavigationItems() {
|
|
|
18187
19978
|
).filter((el) => isNavigationItem2(el));
|
|
18188
19979
|
}
|
|
18189
19980
|
function getNavigationItemReorderState(anchor) {
|
|
18190
|
-
if (isCtaButton(anchor))
|
|
19981
|
+
if (isCtaButton(anchor)) {
|
|
19982
|
+
if (!collectionDragEnabled(anchor)) return { key: null, disabled: true };
|
|
19983
|
+
return { key: buttonId(anchor), disabled: false };
|
|
19984
|
+
}
|
|
18191
19985
|
return getReorderHandleStateFromAnchor(anchor);
|
|
18192
19986
|
}
|
|
18193
19987
|
function getReorderHandleState(el) {
|
|
@@ -18286,6 +20080,12 @@ function isPointOverNavigation(x, y) {
|
|
|
18286
20080
|
const r2 = panel.getBoundingClientRect();
|
|
18287
20081
|
if (x >= r2.left && x <= r2.right && y >= r2.top && y <= r2.bottom) return true;
|
|
18288
20082
|
}
|
|
20083
|
+
for (const el of document.querySelectorAll('[data-ohw-role="navbar-button"]')) {
|
|
20084
|
+
const r2 = el.getBoundingClientRect();
|
|
20085
|
+
if (r2.width > 0 && r2.height > 0 && x >= r2.left && x <= r2.right && y >= r2.top && y <= r2.bottom) {
|
|
20086
|
+
return true;
|
|
20087
|
+
}
|
|
20088
|
+
}
|
|
18289
20089
|
return false;
|
|
18290
20090
|
}
|
|
18291
20091
|
function findHoveredNavOrFooterContainer(x, y) {
|
|
@@ -18365,7 +20165,7 @@ function getNavigationSelectionParent(el) {
|
|
|
18365
20165
|
if (!isFooterLinksContainer(el) && (el.hasAttribute("data-ohw-footer-col") || el.hasAttribute("data-ohw-footer-column") || isInferredFooterGroup2(el))) {
|
|
18366
20166
|
return getFooterLinksContainer();
|
|
18367
20167
|
}
|
|
18368
|
-
if (el.hasAttribute("data-ohw-nav-container") || el.hasAttribute("data-ohw-nav-drawer") || isFooterLinksContainer(el)) {
|
|
20168
|
+
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)) {
|
|
18369
20169
|
return getNavigationRoot(el);
|
|
18370
20170
|
}
|
|
18371
20171
|
return null;
|
|
@@ -18587,7 +20387,6 @@ var ICONS = {
|
|
|
18587
20387
|
insertUnorderedList: '<line x1="8" y1="6" x2="21" y2="6"/><line x1="8" y1="12" x2="21" y2="12"/><line x1="8" y1="18" x2="21" y2="18"/><line x1="3" y1="6" x2="3.01" y2="6"/><line x1="3" y1="12" x2="3.01" y2="12"/><line x1="3" y1="18" x2="3.01" y2="18"/>',
|
|
18588
20388
|
insertOrderedList: '<line x1="10" y1="6" x2="21" y2="6"/><line x1="10" y1="12" x2="21" y2="12"/><line x1="10" y1="18" x2="21" y2="18"/><path d="M4 6h1v4"/><path d="M4 10h2"/><path d="M6 18H4c0-1 2-2 2-3s-1-1.5-2-1"/>'
|
|
18589
20389
|
};
|
|
18590
|
-
var HEIGHT_SETTLE_DELAYS = [150, 400, 800];
|
|
18591
20390
|
var SELECTION_CHROME_GAP2 = 4;
|
|
18592
20391
|
var TOOLBAR_STROKE_GAP2 = 4;
|
|
18593
20392
|
var TOOLBAR_OFFSET_FROM_ELEMENT = SELECTION_CHROME_GAP2 + TOOLBAR_STROKE_GAP2;
|
|
@@ -18619,7 +20418,7 @@ function EditGlowChrome({
|
|
|
18619
20418
|
hideHandle = false
|
|
18620
20419
|
}) {
|
|
18621
20420
|
const GAP = SELECTION_CHROME_GAP2;
|
|
18622
|
-
return /* @__PURE__ */
|
|
20421
|
+
return /* @__PURE__ */ jsxs23(
|
|
18623
20422
|
"div",
|
|
18624
20423
|
{
|
|
18625
20424
|
ref: elRef,
|
|
@@ -18634,7 +20433,7 @@ function EditGlowChrome({
|
|
|
18634
20433
|
zIndex: 2147483646
|
|
18635
20434
|
},
|
|
18636
20435
|
children: [
|
|
18637
|
-
/* @__PURE__ */
|
|
20436
|
+
/* @__PURE__ */ jsx36(
|
|
18638
20437
|
"div",
|
|
18639
20438
|
{
|
|
18640
20439
|
style: {
|
|
@@ -18648,7 +20447,7 @@ function EditGlowChrome({
|
|
|
18648
20447
|
}
|
|
18649
20448
|
}
|
|
18650
20449
|
),
|
|
18651
|
-
reorderHrefKey && !hideHandle && /* @__PURE__ */
|
|
20450
|
+
reorderHrefKey && !hideHandle && /* @__PURE__ */ jsx36(
|
|
18652
20451
|
"div",
|
|
18653
20452
|
{
|
|
18654
20453
|
"data-ohw-drag-handle-container": "",
|
|
@@ -18660,7 +20459,7 @@ function EditGlowChrome({
|
|
|
18660
20459
|
transform: "translate(calc(-100% - 7px), -50%)",
|
|
18661
20460
|
pointerEvents: dragDisabled ? "none" : "auto"
|
|
18662
20461
|
},
|
|
18663
|
-
children: /* @__PURE__ */
|
|
20462
|
+
children: /* @__PURE__ */ jsx36(
|
|
18664
20463
|
DragHandle,
|
|
18665
20464
|
{
|
|
18666
20465
|
"aria-label": `Reorder ${reorderHrefKey}`,
|
|
@@ -18674,22 +20473,12 @@ function EditGlowChrome({
|
|
|
18674
20473
|
}
|
|
18675
20474
|
);
|
|
18676
20475
|
}
|
|
18677
|
-
function getIframeVisibleClip(parentScroll) {
|
|
18678
|
-
if (!parentScroll) return null;
|
|
18679
|
-
const { iframeOffsetTop, headerH: visibleCanvasTop, canvasH } = parentScroll;
|
|
18680
|
-
const clipTop = Math.max(0, visibleCanvasTop - iframeOffsetTop);
|
|
18681
|
-
const clipBottom = Math.min(
|
|
18682
|
-
window.innerHeight,
|
|
18683
|
-
visibleCanvasTop + canvasH - iframeOffsetTop
|
|
18684
|
-
);
|
|
18685
|
-
return { top: clipTop, bottom: Math.max(clipTop, clipBottom) };
|
|
18686
|
-
}
|
|
18687
20476
|
function isRectOutsideClip(rect, clip) {
|
|
18688
20477
|
if (!clip) return false;
|
|
18689
20478
|
return rect.bottom < clip.top || rect.top > clip.bottom;
|
|
18690
20479
|
}
|
|
18691
20480
|
function applyVisibleViewport(el, parentScroll) {
|
|
18692
|
-
const clip =
|
|
20481
|
+
const clip = getIframeChromeClip(parentScroll);
|
|
18693
20482
|
const top = clip?.top ?? 0;
|
|
18694
20483
|
const height = clip ? clip.bottom - clip.top : window.innerHeight;
|
|
18695
20484
|
el.style.top = `${top}px`;
|
|
@@ -18729,7 +20518,7 @@ function clampToolbarLeft(centerX, toolbarWidth) {
|
|
|
18729
20518
|
function calcToolbarPos(rect, parentScroll, toolbarW = 306) {
|
|
18730
20519
|
const GAP = TOOLBAR_OFFSET_FROM_ELEMENT;
|
|
18731
20520
|
const APPROX_H = 32;
|
|
18732
|
-
const clip =
|
|
20521
|
+
const clip = getIframeChromeClip(parentScroll);
|
|
18733
20522
|
const clipTop = clip?.top ?? 0;
|
|
18734
20523
|
const canvasTopInIframe = parentScroll != null ? parentScroll.headerH - parentScroll.iframeOffsetTop : 0;
|
|
18735
20524
|
const visibleTop = rect.top - canvasTopInIframe;
|
|
@@ -18874,7 +20663,7 @@ function FloatingToolbar({
|
|
|
18874
20663
|
return () => ro.disconnect();
|
|
18875
20664
|
}, [showEditLink, activeCommands]);
|
|
18876
20665
|
const { top, left, transform } = calcToolbarPos(rect, parentScroll, measuredW);
|
|
18877
|
-
return /* @__PURE__ */
|
|
20666
|
+
return /* @__PURE__ */ jsx36(
|
|
18878
20667
|
"div",
|
|
18879
20668
|
{
|
|
18880
20669
|
ref: setRefs,
|
|
@@ -18886,12 +20675,12 @@ function FloatingToolbar({
|
|
|
18886
20675
|
zIndex: 2147483647,
|
|
18887
20676
|
pointerEvents: "auto"
|
|
18888
20677
|
},
|
|
18889
|
-
children: /* @__PURE__ */
|
|
18890
|
-
TOOLBAR_GROUPS.map((btns, gi) => /* @__PURE__ */
|
|
18891
|
-
gi > 0 && /* @__PURE__ */
|
|
20678
|
+
children: /* @__PURE__ */ jsxs23(CustomToolbar, { children: [
|
|
20679
|
+
TOOLBAR_GROUPS.map((btns, gi) => /* @__PURE__ */ jsxs23(React12.Fragment, { children: [
|
|
20680
|
+
gi > 0 && /* @__PURE__ */ jsx36(CustomToolbarDivider, {}),
|
|
18892
20681
|
btns.map((btn) => {
|
|
18893
20682
|
const isActive = activeCommands.has(btn.cmd);
|
|
18894
|
-
return /* @__PURE__ */
|
|
20683
|
+
return /* @__PURE__ */ jsx36(
|
|
18895
20684
|
CustomToolbarButton,
|
|
18896
20685
|
{
|
|
18897
20686
|
title: btn.title,
|
|
@@ -18900,7 +20689,7 @@ function FloatingToolbar({
|
|
|
18900
20689
|
e.preventDefault();
|
|
18901
20690
|
onCommand(btn.cmd);
|
|
18902
20691
|
},
|
|
18903
|
-
children: /* @__PURE__ */
|
|
20692
|
+
children: /* @__PURE__ */ jsx36(
|
|
18904
20693
|
"svg",
|
|
18905
20694
|
{
|
|
18906
20695
|
width: "16",
|
|
@@ -18921,7 +20710,7 @@ function FloatingToolbar({
|
|
|
18921
20710
|
);
|
|
18922
20711
|
})
|
|
18923
20712
|
] }, gi)),
|
|
18924
|
-
showEditLink ? /* @__PURE__ */
|
|
20713
|
+
showEditLink ? /* @__PURE__ */ jsx36(
|
|
18925
20714
|
CustomToolbarButton,
|
|
18926
20715
|
{
|
|
18927
20716
|
type: "button",
|
|
@@ -18935,7 +20724,7 @@ function FloatingToolbar({
|
|
|
18935
20724
|
e.preventDefault();
|
|
18936
20725
|
e.stopPropagation();
|
|
18937
20726
|
},
|
|
18938
|
-
children: /* @__PURE__ */
|
|
20727
|
+
children: /* @__PURE__ */ jsx36(Link2, { className: "size-4 shrink-0", "aria-hidden": true })
|
|
18939
20728
|
}
|
|
18940
20729
|
) : null
|
|
18941
20730
|
] })
|
|
@@ -18952,7 +20741,7 @@ function StateToggle({
|
|
|
18952
20741
|
states,
|
|
18953
20742
|
onStateChange
|
|
18954
20743
|
}) {
|
|
18955
|
-
return /* @__PURE__ */
|
|
20744
|
+
return /* @__PURE__ */ jsx36(
|
|
18956
20745
|
ToggleGroup,
|
|
18957
20746
|
{
|
|
18958
20747
|
"data-ohw-state-toggle": "",
|
|
@@ -18966,11 +20755,12 @@ function StateToggle({
|
|
|
18966
20755
|
left: rect.right - 8,
|
|
18967
20756
|
transform: "translateX(-100%)"
|
|
18968
20757
|
},
|
|
18969
|
-
children: states.map((state) => /* @__PURE__ */
|
|
20758
|
+
children: states.map((state) => /* @__PURE__ */ jsx36(ToggleGroupItem, { value: state, size: "sm", children: state }, state))
|
|
18970
20759
|
}
|
|
18971
20760
|
);
|
|
18972
20761
|
}
|
|
18973
20762
|
var contentCache = /* @__PURE__ */ new Map();
|
|
20763
|
+
var fetchedContentPaths = /* @__PURE__ */ new Set();
|
|
18974
20764
|
var brandingCache = /* @__PURE__ */ new Map();
|
|
18975
20765
|
var OHW_LOADER_STYLE = {
|
|
18976
20766
|
position: "fixed",
|
|
@@ -18982,9 +20772,9 @@ var OHW_LOADER_STYLE = {
|
|
|
18982
20772
|
justifyContent: "center"
|
|
18983
20773
|
};
|
|
18984
20774
|
function OhwLoaderSpinner() {
|
|
18985
|
-
return /* @__PURE__ */
|
|
18986
|
-
/* @__PURE__ */
|
|
18987
|
-
/* @__PURE__ */
|
|
20775
|
+
return /* @__PURE__ */ jsxs23("svg", { width: "28", height: "28", viewBox: "0 0 28 28", fill: "none", "aria-hidden": true, children: [
|
|
20776
|
+
/* @__PURE__ */ jsx36("circle", { cx: "14", cy: "14", r: "11", stroke: "#E7E5E4", strokeWidth: "3" }),
|
|
20777
|
+
/* @__PURE__ */ jsx36(
|
|
18988
20778
|
"circle",
|
|
18989
20779
|
{
|
|
18990
20780
|
cx: "14",
|
|
@@ -18994,7 +20784,7 @@ function OhwLoaderSpinner() {
|
|
|
18994
20784
|
strokeWidth: "3",
|
|
18995
20785
|
strokeDasharray: "17 52",
|
|
18996
20786
|
strokeLinecap: "round",
|
|
18997
|
-
children: /* @__PURE__ */
|
|
20787
|
+
children: /* @__PURE__ */ jsx36(
|
|
18998
20788
|
"animateTransform",
|
|
18999
20789
|
{
|
|
19000
20790
|
attributeName: "transform",
|
|
@@ -19010,7 +20800,7 @@ function OhwLoaderSpinner() {
|
|
|
19010
20800
|
] });
|
|
19011
20801
|
}
|
|
19012
20802
|
function OhwBrandMark() {
|
|
19013
|
-
return /* @__PURE__ */
|
|
20803
|
+
return /* @__PURE__ */ jsxs23(
|
|
19014
20804
|
"svg",
|
|
19015
20805
|
{
|
|
19016
20806
|
width: "16",
|
|
@@ -19021,7 +20811,7 @@ function OhwBrandMark() {
|
|
|
19021
20811
|
style: { display: "block", flexShrink: 0 },
|
|
19022
20812
|
xmlns: "http://www.w3.org/2000/svg",
|
|
19023
20813
|
children: [
|
|
19024
|
-
/* @__PURE__ */
|
|
20814
|
+
/* @__PURE__ */ jsx36(
|
|
19025
20815
|
"mask",
|
|
19026
20816
|
{
|
|
19027
20817
|
id: "ohw-badge-mark",
|
|
@@ -19031,15 +20821,15 @@ function OhwBrandMark() {
|
|
|
19031
20821
|
y: "0",
|
|
19032
20822
|
width: "48",
|
|
19033
20823
|
height: "48",
|
|
19034
|
-
children: /* @__PURE__ */
|
|
20824
|
+
children: /* @__PURE__ */ jsx36("path", { d: "M23.8741 48C37.0594 48 47.7481 37.2548 47.7481 24C47.7481 10.7452 37.0594 0 23.8741 0C10.6888 0 0 10.7452 0 24C0 37.2548 10.6888 48 23.8741 48Z", fill: "white" })
|
|
19035
20825
|
}
|
|
19036
20826
|
),
|
|
19037
|
-
/* @__PURE__ */
|
|
19038
|
-
/* @__PURE__ */
|
|
19039
|
-
/* @__PURE__ */
|
|
19040
|
-
/* @__PURE__ */
|
|
19041
|
-
/* @__PURE__ */
|
|
19042
|
-
/* @__PURE__ */
|
|
20827
|
+
/* @__PURE__ */ jsxs23("g", { mask: "url(#ohw-badge-mark)", children: [
|
|
20828
|
+
/* @__PURE__ */ jsx36("path", { d: "M23.8731 48.0497C37.0584 48.0497 47.7472 37.3046 47.7472 24.0497C47.7472 10.7949 37.0584 0.0497208 23.8731 0.0497208C10.6878 0.0497208 -0.000976562 10.7949 -0.000976562 24.0497C-0.000976562 37.3046 10.6878 48.0497 23.8731 48.0497Z", fill: "#0078E5" }),
|
|
20829
|
+
/* @__PURE__ */ jsx36("path", { d: "M17.1307 14.7172C13.1687 14.7172 9.38102 18.1154 8.65114 22.34C8.38885 23.8488 8.5598 25.2581 9.06929 26.4451C6.20005 29.1677 1.77216 27.8721 -1.40212 26.1536C-2.73618 25.4317 -3.92695 27.4745 -2.59037 28.1981C1.33389 30.3226 6.86037 31.6621 10.4402 28.4188C11.4718 29.3859 12.867 29.9621 14.4894 29.9621C18.4161 29.9621 22.2038 26.5318 22.9337 22.34C23.6636 18.1162 21.0566 14.7172 17.1298 14.7172H17.1307ZM19.9798 22.34C19.5281 25.0399 17.2689 27.231 14.9754 27.231C12.6466 27.231 11.1877 25.0399 11.6394 22.34C12.1262 19.6401 14.3151 17.4482 16.6438 17.4482C18.9374 17.4482 20.4667 19.6401 19.9798 22.34Z", fill: "white" }),
|
|
20830
|
+
/* @__PURE__ */ jsx36("path", { d: "M40.0017 27.0262C39.1797 27.081 38.2721 26.995 37.4668 26.7415C37.3344 26.6993 37.28 26.5401 37.3529 26.4205C37.5959 26.0212 37.8255 25.6152 38.009 25.1889C38.1071 24.9918 38.2018 24.793 38.2897 24.5908C38.3274 24.5041 38.4163 24.451 38.5101 24.4619C38.63 24.4754 38.7054 24.4821 38.8881 24.4821L39.1529 24.4796L39.8283 24.4543C45.9229 24.0492 50.4765 20.4319 54.8466 16.9014C56.0172 15.9554 57.6932 17.6208 56.5116 18.5752C51.7687 22.4065 47.1966 26.5081 40.9319 26.9689", fill: "white" }),
|
|
20831
|
+
/* @__PURE__ */ jsx36("path", { d: "M37.9687 24.27C38.4472 23.1319 38.7656 21.9045 38.9609 20.6991C39.5927 16.76 38.5058 14.2193 36.1553 14.2193C34.1835 14.2193 33.1469 17.2427 32.9199 18.8694C32.743 19.9872 32.5914 22.1219 33.6028 23.9524C33.7553 24.259 34.15 24.7712 34.471 25.1259C34.5447 25.2067 34.6746 25.2 34.7349 25.1082C34.9528 24.7788 35.1615 24.4039 35.3584 24.0257C35.5444 23.6677 35.5888 23.6138 35.8587 23.0207C35.8838 22.966 35.8813 22.9002 35.8478 22.8505C35.5888 22.4597 35.2168 21.9787 35.1204 21.4614C34.9184 20.4455 34.9436 19.2257 35.2218 18.1078C35.4413 17.3118 35.7195 16.7844 35.9039 16.5106C35.9466 16.4466 36.0279 16.4129 36.0975 16.4449C36.369 16.5671 36.5827 16.8838 36.7385 17.396C37.0167 18.2089 37.0167 19.3782 36.814 20.6999C36.6991 21.5271 36.4771 22.3729 36.1746 23.1673C36.1293 23.308 36.0757 23.4461 36.0187 23.5826C36.0187 23.5868 36.0187 23.591 36.0187 23.5961C35.9911 23.6946 35.9207 23.8067 35.8846 23.901C35.5536 24.5497 35.2344 25.1697 34.8439 25.7838C34.8388 25.7863 34.8346 25.7914 34.8296 25.7931C34.6528 26.0525 34.4718 26.2901 34.2866 26.4965C34.2774 26.5099 34.2682 26.5234 34.2589 26.5369C34.2405 26.5638 34.2179 26.5815 34.1944 26.595C33.5064 27.3212 32.7665 27.6893 32.0123 27.6893C31.8606 27.6893 31.6838 27.664 31.507 27.4349C31.3042 27.1299 30.85 26.0879 31.2539 22.9112C31.4785 21.3949 31.8011 20.0268 31.931 19.5408C31.9579 19.4413 31.8908 19.3419 31.7886 19.3293L30.0062 19.1162C29.9241 19.1061 29.8478 19.1566 29.8252 19.2366C29.2704 21.1615 27.0305 27.6885 24.9599 27.6885C24.328 27.6885 24.1512 26.6211 24.1001 26.2909C23.775 23.6264 25.528 18.5492 29.5302 16.2267C29.6048 16.1838 29.635 16.0928 29.5998 16.0136L28.9042 14.467C28.8632 14.3752 28.7501 14.3389 28.6638 14.3886C25.8079 16.0414 24.1847 18.5231 23.2915 20.3436C22.2046 22.5793 21.6993 25.0189 21.9515 26.8738C22.1795 28.7794 23.1398 29.872 24.6054 29.872C26.0543 29.872 27.4369 28.9066 28.7098 27.0187C28.7953 26.8915 28.9889 26.9311 29.0149 27.0819C29.2646 28.5283 29.9811 29.872 31.6579 29.872C33.5282 29.872 35.3232 28.7288 36.7134 26.6447C36.7712 26.5874 36.7972 26.5411 36.8181 26.4906C36.8232 26.4931 36.8282 26.4948 36.8332 26.4973C37.01 26.2025 37.181 25.9051 37.3444 25.6027C37.4508 25.4005 37.5572 25.1992 37.6586 24.9945C37.7181 24.874 37.7743 24.7527 37.8262 24.6289C37.838 24.6002 37.8547 24.5665 37.8706 24.5337", fill: "white" }),
|
|
20832
|
+
/* @__PURE__ */ jsx36("path", { d: "M30.5839 31.6397C25.7546 34.8577 19.4773 34.7853 14.6907 31.5243C13.5368 30.7384 12.5044 32.6498 13.6474 33.4281C19.034 37.0985 26.3077 37.096 31.7218 33.488C32.8791 32.7172 31.7478 30.8639 30.5839 31.6397Z", fill: "white" })
|
|
19043
20833
|
] })
|
|
19044
20834
|
]
|
|
19045
20835
|
}
|
|
@@ -19076,7 +20866,7 @@ var OHW_BADGE_LABEL_STYLE = {
|
|
|
19076
20866
|
whiteSpace: "nowrap"
|
|
19077
20867
|
};
|
|
19078
20868
|
function MadeWithOhhWells() {
|
|
19079
|
-
return /* @__PURE__ */
|
|
20869
|
+
return /* @__PURE__ */ jsxs23(
|
|
19080
20870
|
"a",
|
|
19081
20871
|
{
|
|
19082
20872
|
href: "https://ohhwells.com",
|
|
@@ -19086,8 +20876,8 @@ function MadeWithOhhWells() {
|
|
|
19086
20876
|
"data-ohw-badge": "",
|
|
19087
20877
|
style: OHW_BADGE_STYLE,
|
|
19088
20878
|
children: [
|
|
19089
|
-
/* @__PURE__ */
|
|
19090
|
-
/* @__PURE__ */
|
|
20879
|
+
/* @__PURE__ */ jsx36(OhwBrandMark, {}),
|
|
20880
|
+
/* @__PURE__ */ jsx36("span", { style: OHW_BADGE_LABEL_STYLE, children: "Made with OhhWells" })
|
|
19091
20881
|
]
|
|
19092
20882
|
}
|
|
19093
20883
|
);
|
|
@@ -19574,13 +21364,6 @@ function OhhwellsBridge() {
|
|
|
19574
21364
|
const [isItemDragging, setIsItemDragging] = useState16(false);
|
|
19575
21365
|
const [isFooterFrameSelection, setIsFooterFrameSelection] = useState16(false);
|
|
19576
21366
|
isFooterFrameSelectionRef.current = isFooterFrameSelection;
|
|
19577
|
-
const [floatingPanel, setFloatingPanel] = useState16(null);
|
|
19578
|
-
const floatingPanelOpenRef = useRef12(false);
|
|
19579
|
-
floatingPanelOpenRef.current = floatingPanel !== null;
|
|
19580
|
-
const [floatingPanelPos, setFloatingPanelPos] = useState16(null);
|
|
19581
|
-
const [logoSizeDraft, setLogoSizeDraft] = useState16(null);
|
|
19582
|
-
const [editorViewport, setEditorViewport] = useState16("desktop");
|
|
19583
|
-
const [parentScrollSnap, setParentScrollSnap] = useState16(null);
|
|
19584
21367
|
const [navDropdownPreviewOpen, setNavDropdownPreviewOpen] = useState16(null);
|
|
19585
21368
|
const [footerHeadingVisible, setFooterHeadingVisible] = useState16(null);
|
|
19586
21369
|
const footerDragRef = useRef12(null);
|
|
@@ -19604,6 +21387,21 @@ function OhhwellsBridge() {
|
|
|
19604
21387
|
const stylesRef = useRef12("");
|
|
19605
21388
|
const appliedDrawerRef = useRef12(null);
|
|
19606
21389
|
const pendingDeleteUndoRef = useRef12(null);
|
|
21390
|
+
const [floatingPanel, setFloatingPanel] = useState16(null);
|
|
21391
|
+
const floatingPanelOpenRef = useRef12(false);
|
|
21392
|
+
const floatingPanelRef = useRef12(null);
|
|
21393
|
+
floatingPanelRef.current = floatingPanel;
|
|
21394
|
+
const setFloatingPanelRef = useRef12(setFloatingPanel);
|
|
21395
|
+
const [floatingPanelPos, setFloatingPanelPos] = useState16(null);
|
|
21396
|
+
const buttonCollectionDragRef = useRef12(null);
|
|
21397
|
+
const buttonDropInsertIndexRef = useRef12(null);
|
|
21398
|
+
const [buttonDropSlots, setButtonDropSlots] = useState16([]);
|
|
21399
|
+
const [activeButtonDropIndex, setActiveButtonDropIndex] = useState16(null);
|
|
21400
|
+
const buttonPointerDragRef = useRef12(null);
|
|
21401
|
+
const [buttonStyleTick, setButtonStyleTick] = useState16(0);
|
|
21402
|
+
const [logoSizeDraft, setLogoSizeDraft] = useState16(null);
|
|
21403
|
+
const [editorViewport, setEditorViewport] = useState16("desktop");
|
|
21404
|
+
const [parentScrollSnap, setParentScrollSnap] = useState16(null);
|
|
19607
21405
|
const [sitePages, setSitePages] = useState16([]);
|
|
19608
21406
|
const [sectionsByPath, setSectionsByPath] = useState16({});
|
|
19609
21407
|
const sectionsPrefetchGenRef = useRef12(0);
|
|
@@ -19612,7 +21410,18 @@ function OhhwellsBridge() {
|
|
|
19612
21410
|
const linkPopoverOpenRef = useRef12(false);
|
|
19613
21411
|
const linkPopoverGraceUntilRef = useRef12(0);
|
|
19614
21412
|
setLinkPopoverRef.current = setLinkPopover;
|
|
21413
|
+
setFloatingPanelRef.current = setFloatingPanel;
|
|
19615
21414
|
linkPopoverSessionRef.current = linkPopover;
|
|
21415
|
+
floatingPanelOpenRef.current = Boolean(floatingPanel);
|
|
21416
|
+
useEffect15(() => {
|
|
21417
|
+
const syncViewport = () => {
|
|
21418
|
+
const next = window.innerWidth <= 480 ? "mobile" : "desktop";
|
|
21419
|
+
setEditorViewport((prev) => prev === next ? prev : next);
|
|
21420
|
+
};
|
|
21421
|
+
syncViewport();
|
|
21422
|
+
window.addEventListener("resize", syncViewport);
|
|
21423
|
+
return () => window.removeEventListener("resize", syncViewport);
|
|
21424
|
+
}, []);
|
|
19616
21425
|
useEffect15(() => {
|
|
19617
21426
|
setSectionOrderPersistHandler((entries) => {
|
|
19618
21427
|
const currentPath = window.location.pathname;
|
|
@@ -19878,6 +21687,7 @@ function OhhwellsBridge() {
|
|
|
19878
21687
|
hoveredItemElRef.current = null;
|
|
19879
21688
|
setHoveredItemRect(null);
|
|
19880
21689
|
setFloatingPanel(null);
|
|
21690
|
+
setFloatingPanelPos(null);
|
|
19881
21691
|
setLogoSizeDraft(null);
|
|
19882
21692
|
if (!activeElRef.current) {
|
|
19883
21693
|
if (nestedGroup?.isConnected) {
|
|
@@ -20478,6 +22288,47 @@ function OhhwellsBridge() {
|
|
|
20478
22288
|
},
|
|
20479
22289
|
[beginFooterDrag]
|
|
20480
22290
|
);
|
|
22291
|
+
const persistButtonCollectionDrag = useCallback10(
|
|
22292
|
+
(button, clientX) => {
|
|
22293
|
+
const insertIndex = buttonDropInsertIndexRef.current;
|
|
22294
|
+
if (insertIndex != null) insertButtonAtCollectionIndex(button, insertIndex);
|
|
22295
|
+
else if (typeof clientX === "number" && clientX !== 0) reorderButtonInCollection(button, clientX);
|
|
22296
|
+
buttonDropInsertIndexRef.current = null;
|
|
22297
|
+
const collection = buttonCollectionOf(button);
|
|
22298
|
+
if (collection) {
|
|
22299
|
+
const persisted = persistCollectionOrder(collection, editContentRef.current);
|
|
22300
|
+
if (persisted) {
|
|
22301
|
+
editContentRef.current = persisted.content;
|
|
22302
|
+
postToParent2({ type: "ow:change", nodes: persisted.nodes });
|
|
22303
|
+
}
|
|
22304
|
+
}
|
|
22305
|
+
buttonCollectionDragRef.current = null;
|
|
22306
|
+
buttonPointerDragRef.current = null;
|
|
22307
|
+
setButtonDropSlots([]);
|
|
22308
|
+
setActiveButtonDropIndex(null);
|
|
22309
|
+
setIsItemDragging(false);
|
|
22310
|
+
unlockFooterDragInteraction();
|
|
22311
|
+
if (button.isConnected) setToolbarRect(button.getBoundingClientRect());
|
|
22312
|
+
},
|
|
22313
|
+
[postToParent2]
|
|
22314
|
+
);
|
|
22315
|
+
const refreshButtonDragVisuals = useCallback10((button, clientX, clientY) => {
|
|
22316
|
+
const collection = buttonCollectionOf(button);
|
|
22317
|
+
if (!collection) {
|
|
22318
|
+
setButtonDropSlots([]);
|
|
22319
|
+
setActiveButtonDropIndex(null);
|
|
22320
|
+
buttonDropInsertIndexRef.current = null;
|
|
22321
|
+
return;
|
|
22322
|
+
}
|
|
22323
|
+
const slots = buildButtonCollectionDropSlots(collection);
|
|
22324
|
+
const active = hitTestButtonCollectionDropSlot(collection, clientX, clientY);
|
|
22325
|
+
setButtonDropSlots(slots);
|
|
22326
|
+
const idx = active ? slots.findIndex((slot) => slot.insertIndex === active.insertIndex) : -1;
|
|
22327
|
+
setActiveButtonDropIndex(idx >= 0 ? idx : null);
|
|
22328
|
+
buttonDropInsertIndexRef.current = active?.insertIndex ?? null;
|
|
22329
|
+
setDraggedItemRect(button.getBoundingClientRect());
|
|
22330
|
+
if (selectedElRef.current === button) setToolbarRect(button.getBoundingClientRect());
|
|
22331
|
+
}, []);
|
|
20481
22332
|
const handleItemDragStart = useCallback10(
|
|
20482
22333
|
(e) => {
|
|
20483
22334
|
const selected = selectedElRef.current;
|
|
@@ -20487,6 +22338,17 @@ function OhhwellsBridge() {
|
|
|
20487
22338
|
}
|
|
20488
22339
|
const clientX = e?.clientX ?? selected.getBoundingClientRect().left + 8;
|
|
20489
22340
|
const clientY = e?.clientY ?? selected.getBoundingClientRect().top + 8;
|
|
22341
|
+
if (isCtaButton(selected) && collectionDragEnabled(selected)) {
|
|
22342
|
+
buttonCollectionDragRef.current = selected;
|
|
22343
|
+
setMediaHover(null);
|
|
22344
|
+
if (e?.dataTransfer) {
|
|
22345
|
+
e.dataTransfer.effectAllowed = "move";
|
|
22346
|
+
e.dataTransfer.setData("text/plain", buttonId(selected) ?? "button");
|
|
22347
|
+
}
|
|
22348
|
+
setIsItemDragging(true);
|
|
22349
|
+
refreshButtonDragVisuals(selected, clientX, clientY);
|
|
22350
|
+
return;
|
|
22351
|
+
}
|
|
20490
22352
|
if (startFooterLinkDrag(selected, clientX, clientY, true)) return;
|
|
20491
22353
|
if (selected.hasAttribute("data-ohw-footer-col") || isInferredFooterGroup2(selected) && selected.closest("footer")) {
|
|
20492
22354
|
if (startFooterColumnDrag(selected, clientX, clientY, true)) return;
|
|
@@ -20496,10 +22358,15 @@ function OhhwellsBridge() {
|
|
|
20496
22358
|
setSiblingHintRect(null);
|
|
20497
22359
|
setIsItemDragging(true);
|
|
20498
22360
|
},
|
|
20499
|
-
[startFooterColumnDrag, startFooterLinkDrag, startNavLinkDrag]
|
|
22361
|
+
[startFooterColumnDrag, startFooterLinkDrag, startNavLinkDrag, refreshButtonDragVisuals]
|
|
20500
22362
|
);
|
|
20501
22363
|
const handleItemDragEnd = useCallback10(
|
|
20502
22364
|
(e) => {
|
|
22365
|
+
const collectionButton = buttonCollectionDragRef.current;
|
|
22366
|
+
if (collectionButton) {
|
|
22367
|
+
persistButtonCollectionDrag(collectionButton, e?.clientX);
|
|
22368
|
+
return;
|
|
22369
|
+
}
|
|
20503
22370
|
if (footerDragRef.current) {
|
|
20504
22371
|
const x = e?.clientX;
|
|
20505
22372
|
const y = e?.clientY;
|
|
@@ -20522,12 +22389,22 @@ function OhhwellsBridge() {
|
|
|
20522
22389
|
}
|
|
20523
22390
|
setIsItemDragging(false);
|
|
20524
22391
|
},
|
|
20525
|
-
[commitFooterDrag, commitNavDrag, navDragRef]
|
|
22392
|
+
[commitFooterDrag, commitNavDrag, navDragRef, persistButtonCollectionDrag]
|
|
20526
22393
|
);
|
|
20527
22394
|
const handleItemChromePointerDown = useCallback10((e) => {
|
|
20528
22395
|
if (e.button !== 0) return;
|
|
20529
22396
|
const selected = selectedElRef.current;
|
|
20530
22397
|
if (!selected) return;
|
|
22398
|
+
if (isCtaButton(selected) && collectionDragEnabled(selected)) {
|
|
22399
|
+
buttonPointerDragRef.current = {
|
|
22400
|
+
el: selected,
|
|
22401
|
+
startX: e.clientX,
|
|
22402
|
+
startY: e.clientY,
|
|
22403
|
+
pointerId: e.pointerId,
|
|
22404
|
+
started: false
|
|
22405
|
+
};
|
|
22406
|
+
return;
|
|
22407
|
+
}
|
|
20531
22408
|
const hrefKey = selected.getAttribute("data-ohw-href-key");
|
|
20532
22409
|
if (hrefKey && isFooterHrefKey(hrefKey)) {
|
|
20533
22410
|
footerPointerDragRef.current = {
|
|
@@ -20606,10 +22483,29 @@ function OhhwellsBridge() {
|
|
|
20606
22483
|
setIsFooterFrameSelection(false);
|
|
20607
22484
|
setToolbarVariant("link-action");
|
|
20608
22485
|
setToolbarRect(anchor.getBoundingClientRect());
|
|
22486
|
+
if (glowElRef.current) glowElRef.current.style.display = "";
|
|
20609
22487
|
setToolbarShowEditLink(false);
|
|
20610
22488
|
setActiveCommands(/* @__PURE__ */ new Set());
|
|
20611
|
-
|
|
20612
|
-
|
|
22489
|
+
const panel = floatingPanelRef.current;
|
|
22490
|
+
if (panel?.kind === "button-style" && isCtaButton(anchor)) {
|
|
22491
|
+
const id = buttonId(anchor);
|
|
22492
|
+
if (id && panel.buttonId !== id) {
|
|
22493
|
+
captureButtonOrigin(anchor);
|
|
22494
|
+
setFloatingPanelPos(null);
|
|
22495
|
+
setParentScrollSnap(parentScrollRef.current);
|
|
22496
|
+
setFloatingPanel({
|
|
22497
|
+
...panel,
|
|
22498
|
+
key: `button-style:${id}`,
|
|
22499
|
+
buttonId: id,
|
|
22500
|
+
context: buttonStyleContext(anchor)
|
|
22501
|
+
});
|
|
22502
|
+
setButtonStyleTick((n) => n + 1);
|
|
22503
|
+
}
|
|
22504
|
+
} else {
|
|
22505
|
+
setFloatingPanel(null);
|
|
22506
|
+
setFloatingPanelPos(null);
|
|
22507
|
+
setLogoSizeDraft(null);
|
|
22508
|
+
}
|
|
20613
22509
|
}, [deactivate, markSelected]);
|
|
20614
22510
|
const selectFrame = useCallback10((el) => {
|
|
20615
22511
|
if (!isNavigationContainer(el)) return;
|
|
@@ -20649,6 +22545,7 @@ function OhhwellsBridge() {
|
|
|
20649
22545
|
setToolbarShowEditLink(false);
|
|
20650
22546
|
setActiveCommands(/* @__PURE__ */ new Set());
|
|
20651
22547
|
setFloatingPanel(null);
|
|
22548
|
+
setFloatingPanelPos(null);
|
|
20652
22549
|
setLogoSizeDraft(null);
|
|
20653
22550
|
}, [deactivate, markSelected, postToParent2]);
|
|
20654
22551
|
const selectLogo = useCallback10(
|
|
@@ -20694,6 +22591,7 @@ function OhhwellsBridge() {
|
|
|
20694
22591
|
});
|
|
20695
22592
|
}, []);
|
|
20696
22593
|
const openSocialsDisplayPanel = useCallback10((row) => {
|
|
22594
|
+
setFloatingPanelPos(null);
|
|
20697
22595
|
setParentScrollSnap(parentScrollRef.current);
|
|
20698
22596
|
setFloatingPanel({
|
|
20699
22597
|
key: "socials-display",
|
|
@@ -20703,6 +22601,87 @@ function OhhwellsBridge() {
|
|
|
20703
22601
|
row
|
|
20704
22602
|
});
|
|
20705
22603
|
}, []);
|
|
22604
|
+
const rememberButtonTokens = useCallback10(
|
|
22605
|
+
(content, tokens, nodes) => {
|
|
22606
|
+
if (nodes.length === 0) return content;
|
|
22607
|
+
const next = { ...content };
|
|
22608
|
+
for (const node of nodes) next[node.key] = node.text;
|
|
22609
|
+
editContentRef.current = next;
|
|
22610
|
+
postToParent2({ type: "ow:change", nodes });
|
|
22611
|
+
return next;
|
|
22612
|
+
},
|
|
22613
|
+
[postToParent2]
|
|
22614
|
+
);
|
|
22615
|
+
const tokensForButton = useCallback10(
|
|
22616
|
+
(el, persistFallback = false) => {
|
|
22617
|
+
const stored = readStoredStyleTokens(editContentRef.current);
|
|
22618
|
+
if (stored) return stored;
|
|
22619
|
+
const ensured = ensureButtonStyleTokens(document, editContentRef.current);
|
|
22620
|
+
if (ensured.tokens) {
|
|
22621
|
+
rememberButtonTokens(editContentRef.current, ensured.tokens, ensured.nodes);
|
|
22622
|
+
return ensured.tokens;
|
|
22623
|
+
}
|
|
22624
|
+
const fallback = tokensFromButton(el);
|
|
22625
|
+
if (persistFallback) rememberButtonTokens(editContentRef.current, fallback, styleTokenNodes(fallback));
|
|
22626
|
+
return fallback;
|
|
22627
|
+
},
|
|
22628
|
+
[rememberButtonTokens]
|
|
22629
|
+
);
|
|
22630
|
+
const openButtonStylePanel = useCallback10(
|
|
22631
|
+
(anchor) => {
|
|
22632
|
+
const id = buttonId(anchor);
|
|
22633
|
+
if (!id) return;
|
|
22634
|
+
captureButtonOrigin(anchor);
|
|
22635
|
+
tokensForButton(anchor);
|
|
22636
|
+
setFloatingPanelPos(null);
|
|
22637
|
+
setParentScrollSnap(parentScrollRef.current);
|
|
22638
|
+
setFloatingPanel({
|
|
22639
|
+
key: `button-style:${id}`,
|
|
22640
|
+
title: "Style",
|
|
22641
|
+
context: buttonStyleContext(anchor),
|
|
22642
|
+
kind: "button-style",
|
|
22643
|
+
buttonId: id
|
|
22644
|
+
});
|
|
22645
|
+
},
|
|
22646
|
+
[tokensForButton]
|
|
22647
|
+
);
|
|
22648
|
+
const applySelectedButtonStyle = useCallback10(
|
|
22649
|
+
(patch) => {
|
|
22650
|
+
const panel = floatingPanelRef.current;
|
|
22651
|
+
const id = panel?.kind === "button-style" ? panel.buttonId : null;
|
|
22652
|
+
const el = id ? document.querySelector(`[data-ohw-href-key="${CSS.escape(id)}"]`) : null;
|
|
22653
|
+
if (!el || !id || !isCtaButton(el)) return;
|
|
22654
|
+
const tokens = tokensFromButton(el);
|
|
22655
|
+
const next = { ...assignmentFor(el, editContentRef.current, tokens), ...patch };
|
|
22656
|
+
const assignments = withAssignment(editContentRef.current, id, next);
|
|
22657
|
+
const text = JSON.stringify(assignments);
|
|
22658
|
+
editContentRef.current = { ...editContentRef.current, [BUTTON_ASSIGNMENTS_KEY]: text };
|
|
22659
|
+
applyButtonStyle(el, next, tokens);
|
|
22660
|
+
postToParent2({ type: "ow:change", nodes: [{ key: BUTTON_ASSIGNMENTS_KEY, text }] });
|
|
22661
|
+
setButtonStyleTick((n) => n + 1);
|
|
22662
|
+
if (selectedElRef.current === el) setToolbarRect(el.getBoundingClientRect());
|
|
22663
|
+
},
|
|
22664
|
+
[postToParent2]
|
|
22665
|
+
);
|
|
22666
|
+
useEffect15(() => {
|
|
22667
|
+
const onDragOver = (e) => {
|
|
22668
|
+
const dragged = buttonCollectionDragRef.current;
|
|
22669
|
+
if (!dragged) return;
|
|
22670
|
+
e.preventDefault();
|
|
22671
|
+
if (e.dataTransfer) e.dataTransfer.dropEffect = "move";
|
|
22672
|
+
refreshButtonDragVisuals(dragged, e.clientX, e.clientY);
|
|
22673
|
+
};
|
|
22674
|
+
const onDrop = (e) => {
|
|
22675
|
+
if (!buttonCollectionDragRef.current) return;
|
|
22676
|
+
e.preventDefault();
|
|
22677
|
+
};
|
|
22678
|
+
document.addEventListener("dragover", onDragOver);
|
|
22679
|
+
document.addEventListener("drop", onDrop);
|
|
22680
|
+
return () => {
|
|
22681
|
+
document.removeEventListener("dragover", onDragOver);
|
|
22682
|
+
document.removeEventListener("drop", onDrop);
|
|
22683
|
+
};
|
|
22684
|
+
}, [refreshButtonDragVisuals]);
|
|
20706
22685
|
const isEditModeRef = useRef12(false);
|
|
20707
22686
|
const requestMissingSocialIconsRef = useRef12(() => {
|
|
20708
22687
|
});
|
|
@@ -20745,11 +22724,13 @@ function OhhwellsBridge() {
|
|
|
20745
22724
|
);
|
|
20746
22725
|
const closeFloatingPanelOnly = useCallback10(() => {
|
|
20747
22726
|
setFloatingPanel(null);
|
|
22727
|
+
setFloatingPanelPos(null);
|
|
20748
22728
|
setLogoSizeDraft(null);
|
|
20749
22729
|
}, []);
|
|
20750
22730
|
closeFloatingPanelOnlyRef.current = closeFloatingPanelOnly;
|
|
20751
22731
|
const closeFloatingPanelAndDeselect = useCallback10(() => {
|
|
20752
22732
|
setFloatingPanel(null);
|
|
22733
|
+
setFloatingPanelPos(null);
|
|
20753
22734
|
setLogoSizeDraft(null);
|
|
20754
22735
|
deselectRef.current();
|
|
20755
22736
|
}, []);
|
|
@@ -20958,6 +22939,7 @@ function OhhwellsBridge() {
|
|
|
20958
22939
|
}
|
|
20959
22940
|
if (typeof content[STYLE_STORE_KEY] === "string") {
|
|
20960
22941
|
stylesRef.current = content[STYLE_STORE_KEY];
|
|
22942
|
+
document.querySelectorAll('[data-ohw-editable="form"]').forEach((f) => markFormFields(f));
|
|
20961
22943
|
applyStylesToDom(parseStyleStore(content[STYLE_STORE_KEY]));
|
|
20962
22944
|
}
|
|
20963
22945
|
applyBrandChrome(content);
|
|
@@ -20966,12 +22948,12 @@ function OhhwellsBridge() {
|
|
|
20966
22948
|
for (const [key, val] of Object.entries(content)) {
|
|
20967
22949
|
if (key === "__ohw_sections") continue;
|
|
20968
22950
|
if (key === AI_SECTIONS_KEY) continue;
|
|
22951
|
+
if (key === LOGO_PLACEHOLDER_KEY) continue;
|
|
22952
|
+
if (LOGO_IMAGE_KEYS.includes(key)) continue;
|
|
20969
22953
|
if (key === BRAND_KIT_KEY) continue;
|
|
20970
22954
|
if (key === STYLE_STORE_KEY) continue;
|
|
20971
22955
|
if (BRAND_CHROME_KEYS.has(key)) continue;
|
|
20972
|
-
if (key === LOGO_PLACEHOLDER_KEY) continue;
|
|
20973
22956
|
if (key === CUSTOM_CODE_AFTER_HEAD_KEY || key === CUSTOM_CODE_BEFORE_HEAD_KEY) continue;
|
|
20974
|
-
if (LOGO_IMAGE_KEYS.includes(key)) continue;
|
|
20975
22957
|
if (applyVideoSettingNode(key, val)) continue;
|
|
20976
22958
|
if (applyCarouselNode(key, val)) continue;
|
|
20977
22959
|
document.querySelectorAll(`[data-ohw-key="${key}"]`).forEach((el) => {
|
|
@@ -21018,6 +23000,7 @@ function OhhwellsBridge() {
|
|
|
21018
23000
|
reconcileSocialsFromContent(content);
|
|
21019
23001
|
applySocialsDisplayFromContent(content);
|
|
21020
23002
|
applySocialsLabelsFromContent(content, document, { fillEmptyOnly: isEditModeRef.current });
|
|
23003
|
+
syncButtonsFromContent(document, content);
|
|
21021
23004
|
if (isEditModeRef.current) requestMissingSocialIconsRef.current();
|
|
21022
23005
|
if (typeof content[STYLE_STORE_KEY] === "string") {
|
|
21023
23006
|
applyStylesToDom(parseStyleStore(content[STYLE_STORE_KEY]));
|
|
@@ -21042,7 +23025,9 @@ function OhhwellsBridge() {
|
|
|
21042
23025
|
let cancelled = false;
|
|
21043
23026
|
setFetchState("loading");
|
|
21044
23027
|
const apiUrl = process.env.NEXT_PUBLIC_FLOWOPS_API_URL ?? "https://flowops-backend-staging-2yfdh7pwpq-as.a.run.app";
|
|
21045
|
-
|
|
23028
|
+
const initialPath = pathname;
|
|
23029
|
+
fetchedContentPaths.add(`${subdomain}::${initialPath}`);
|
|
23030
|
+
fetch(`${apiUrl}/api/public/sites/${subdomain}/content?path=${encodeURIComponent(initialPath)}`, { cache: "no-store" }).then((r2) => r2.ok ? r2.json() : null).then((data) => {
|
|
21046
23031
|
if (cancelled) return;
|
|
21047
23032
|
const content = data?.content ?? {};
|
|
21048
23033
|
const branding = Boolean(data?.showBranding);
|
|
@@ -21178,16 +23163,17 @@ function OhhwellsBridge() {
|
|
|
21178
23163
|
applyAiSectionsToDom(parseAiSectionsState(content[AI_SECTIONS_KEY]));
|
|
21179
23164
|
}
|
|
21180
23165
|
if (typeof content[STYLE_STORE_KEY] === "string") {
|
|
23166
|
+
document.querySelectorAll('[data-ohw-editable="form"]').forEach((f) => markFormFields(f));
|
|
21181
23167
|
applyStylesToDom(parseStyleStore(content[STYLE_STORE_KEY]));
|
|
21182
23168
|
}
|
|
21183
23169
|
for (const [key, val] of Object.entries(content)) {
|
|
21184
23170
|
if (key === "__ohw_sections") continue;
|
|
21185
23171
|
if (key === AI_SECTIONS_KEY) continue;
|
|
23172
|
+
if (key === LOGO_PLACEHOLDER_KEY) continue;
|
|
23173
|
+
if (LOGO_IMAGE_KEYS.includes(key)) continue;
|
|
21186
23174
|
if (key === BRAND_KIT_KEY) continue;
|
|
21187
23175
|
if (key === STYLE_STORE_KEY) continue;
|
|
21188
23176
|
if (BRAND_CHROME_KEYS.has(key)) continue;
|
|
21189
|
-
if (key === LOGO_PLACEHOLDER_KEY) continue;
|
|
21190
|
-
if (LOGO_IMAGE_KEYS.includes(key)) continue;
|
|
21191
23177
|
if (applyVideoSettingNode(key, val)) continue;
|
|
21192
23178
|
if (applyCarouselNode(key, val)) continue;
|
|
21193
23179
|
document.querySelectorAll(`[data-ohw-key="${key}"]`).forEach((el) => {
|
|
@@ -21218,6 +23204,7 @@ function OhhwellsBridge() {
|
|
|
21218
23204
|
reconcileSocialsFromContent(content);
|
|
21219
23205
|
applySocialsDisplayFromContent(content);
|
|
21220
23206
|
applySocialsLabelsFromContent(content, document, { fillEmptyOnly: isEditModeRef.current });
|
|
23207
|
+
syncButtonsFromContent(document, content);
|
|
21221
23208
|
if (isEditModeRef.current) requestMissingSocialIconsRef.current();
|
|
21222
23209
|
if (typeof content[STYLE_STORE_KEY] === "string") {
|
|
21223
23210
|
applyStylesToDom(parseStyleStore(content[STYLE_STORE_KEY]));
|
|
@@ -21238,6 +23225,17 @@ function OhhwellsBridge() {
|
|
|
21238
23225
|
debounceTimer = setTimeout(applyFromCache, 150);
|
|
21239
23226
|
};
|
|
21240
23227
|
applyFromCache();
|
|
23228
|
+
const pathCacheKey = `${subdomain}::${pathname}`;
|
|
23229
|
+
if (!fetchedContentPaths.has(pathCacheKey)) {
|
|
23230
|
+
fetchedContentPaths.add(pathCacheKey);
|
|
23231
|
+
const apiUrl = process.env.NEXT_PUBLIC_FLOWOPS_API_URL ?? "https://flowops-backend-staging-2yfdh7pwpq-as.a.run.app";
|
|
23232
|
+
fetch(`${apiUrl}/api/public/sites/${subdomain}/content?path=${encodeURIComponent(pathname)}`, { cache: "no-store" }).then((r2) => r2.ok ? r2.json() : null).then((data) => {
|
|
23233
|
+
if (!data?.content) return;
|
|
23234
|
+
contentCache.set(subdomain, data.content);
|
|
23235
|
+
applyFromCache();
|
|
23236
|
+
}).catch(() => {
|
|
23237
|
+
});
|
|
23238
|
+
}
|
|
21241
23239
|
observer = new MutationObserver(scheduleApply);
|
|
21242
23240
|
observer.observe(document.body, { childList: true, subtree: true });
|
|
21243
23241
|
return () => {
|
|
@@ -21306,7 +23304,10 @@ function OhhwellsBridge() {
|
|
|
21306
23304
|
if (roots.length === 0) {
|
|
21307
23305
|
reconcileNavbarItemsFromContent(contentForNav());
|
|
21308
23306
|
reconcileFooterOrderFromContent(contentForNav());
|
|
21309
|
-
if (isEditMode)
|
|
23307
|
+
if (isEditMode) {
|
|
23308
|
+
syncButtonsFromContent(document, contentForNav());
|
|
23309
|
+
syncNavigationDragCursorAttrs();
|
|
23310
|
+
}
|
|
21310
23311
|
return;
|
|
21311
23312
|
}
|
|
21312
23313
|
let rafId = null;
|
|
@@ -21318,7 +23319,7 @@ function OhhwellsBridge() {
|
|
|
21318
23319
|
}
|
|
21319
23320
|
};
|
|
21320
23321
|
const run = () => {
|
|
21321
|
-
if (footerDragRef.current || navDragRef.current || applying) return;
|
|
23322
|
+
if (footerDragRef.current || navDragRef.current || buttonCollectionDragRef.current || applying) return;
|
|
21322
23323
|
applying = true;
|
|
21323
23324
|
observer?.disconnect();
|
|
21324
23325
|
try {
|
|
@@ -21328,6 +23329,7 @@ function OhhwellsBridge() {
|
|
|
21328
23329
|
reconcileSocialsFromContent(content);
|
|
21329
23330
|
applySocialsDisplayFromContent(content);
|
|
21330
23331
|
applySocialsLabelsFromContent(content, document, { fillEmptyOnly: isEditModeRef.current });
|
|
23332
|
+
syncButtonsFromContent(document, content);
|
|
21331
23333
|
if (isEditModeRef.current) requestMissingSocialIconsRef.current();
|
|
21332
23334
|
document.querySelectorAll("footer [data-ohw-href-key]").forEach((el) => {
|
|
21333
23335
|
if (isFooterHrefKey(el.getAttribute("data-ohw-href-key")) || getSocialItem(el)) {
|
|
@@ -21335,9 +23337,9 @@ function OhhwellsBridge() {
|
|
|
21335
23337
|
}
|
|
21336
23338
|
});
|
|
21337
23339
|
document.querySelectorAll(
|
|
21338
|
-
|
|
23340
|
+
'nav [data-ohw-href-key], [data-ohw-nav-container] [data-ohw-href-key], [data-ohw-nav-drawer] [data-ohw-href-key], [data-ohw-role="navbar-button"]'
|
|
21339
23341
|
).forEach((el) => {
|
|
21340
|
-
if (isNavbarHrefKey(el.getAttribute("data-ohw-href-key"))) {
|
|
23342
|
+
if (isNavbarHrefKey(el.getAttribute("data-ohw-href-key")) || isCtaButton(el)) {
|
|
21341
23343
|
disableNativeHrefDrag(el);
|
|
21342
23344
|
}
|
|
21343
23345
|
});
|
|
@@ -21362,6 +23364,44 @@ function OhhwellsBridge() {
|
|
|
21362
23364
|
observer?.disconnect();
|
|
21363
23365
|
};
|
|
21364
23366
|
}, [isEditMode, pathname, subdomain, fetchState, resyncSelectedNavigationItem]);
|
|
23367
|
+
useEffect15(() => {
|
|
23368
|
+
if (!isEditMode) return;
|
|
23369
|
+
let applying = false;
|
|
23370
|
+
let rafId = null;
|
|
23371
|
+
const run = () => {
|
|
23372
|
+
if (applying || buttonCollectionDragRef.current) return;
|
|
23373
|
+
const content = editContentRef.current;
|
|
23374
|
+
if (!content[BUTTON_COLLECTIONS_KEY] && !content[BUTTON_SNAPSHOTS_KEY]) return;
|
|
23375
|
+
applying = true;
|
|
23376
|
+
try {
|
|
23377
|
+
syncButtonsFromContent(document, content);
|
|
23378
|
+
} finally {
|
|
23379
|
+
applying = false;
|
|
23380
|
+
}
|
|
23381
|
+
};
|
|
23382
|
+
const schedule = () => {
|
|
23383
|
+
if (rafId != null) return;
|
|
23384
|
+
rafId = requestAnimationFrame(() => {
|
|
23385
|
+
rafId = null;
|
|
23386
|
+
run();
|
|
23387
|
+
});
|
|
23388
|
+
};
|
|
23389
|
+
const observer = new MutationObserver((mutations) => {
|
|
23390
|
+
if (mutations.every((m) => {
|
|
23391
|
+
const t = m.target;
|
|
23392
|
+
return t instanceof Element && Boolean(t.closest("[data-ohw-bridge], [data-ohw-bridge-root], [data-ohw-button-collection]"));
|
|
23393
|
+
})) {
|
|
23394
|
+
return;
|
|
23395
|
+
}
|
|
23396
|
+
schedule();
|
|
23397
|
+
});
|
|
23398
|
+
observer.observe(document.body, { childList: true, subtree: true });
|
|
23399
|
+
run();
|
|
23400
|
+
return () => {
|
|
23401
|
+
if (rafId != null) cancelAnimationFrame(rafId);
|
|
23402
|
+
observer.disconnect();
|
|
23403
|
+
};
|
|
23404
|
+
}, [isEditMode, pathname]);
|
|
21365
23405
|
useEffect15(() => {
|
|
21366
23406
|
if (!isEditMode) return;
|
|
21367
23407
|
let lastPosted = 0;
|
|
@@ -21384,26 +23424,11 @@ function OhhwellsBridge() {
|
|
|
21384
23424
|
const t2 = setTimeout(measure, 500);
|
|
21385
23425
|
const ro = new ResizeObserver(schedule);
|
|
21386
23426
|
ro.observe(document.body);
|
|
21387
|
-
let lastWidth = window.innerWidth;
|
|
21388
|
-
let resizeTimers = [];
|
|
21389
|
-
const clearResizeTimers = () => {
|
|
21390
|
-
resizeTimers.forEach(clearTimeout);
|
|
21391
|
-
resizeTimers = [];
|
|
21392
|
-
};
|
|
21393
|
-
const handleResize = () => {
|
|
21394
|
-
if (window.innerWidth === lastWidth) return;
|
|
21395
|
-
lastWidth = window.innerWidth;
|
|
21396
|
-
clearResizeTimers();
|
|
21397
|
-
resizeTimers = HEIGHT_SETTLE_DELAYS.map((delay) => setTimeout(measure, delay));
|
|
21398
|
-
};
|
|
21399
|
-
window.addEventListener("resize", handleResize);
|
|
21400
23427
|
return () => {
|
|
21401
23428
|
clearTimeout(t1);
|
|
21402
23429
|
clearTimeout(t2);
|
|
21403
23430
|
if (raf != null) cancelAnimationFrame(raf);
|
|
21404
23431
|
ro.disconnect();
|
|
21405
|
-
clearResizeTimers();
|
|
21406
|
-
window.removeEventListener("resize", handleResize);
|
|
21407
23432
|
};
|
|
21408
23433
|
}, [pathname, isEditMode, postToParent2]);
|
|
21409
23434
|
useEffect15(() => {
|
|
@@ -21698,6 +23723,13 @@ function OhhwellsBridge() {
|
|
|
21698
23723
|
if (target.closest("[data-ohw-state-toggle]")) return;
|
|
21699
23724
|
if (target.closest("[data-ohw-max-badge]")) return;
|
|
21700
23725
|
if (isInsideLinkEditor(target)) return;
|
|
23726
|
+
if (isInsideFloatingPanel(target)) return;
|
|
23727
|
+
if (target.closest("[data-ohw-form-toolbar]")) return;
|
|
23728
|
+
if (target.closest(
|
|
23729
|
+
'[data-ohw-field-toolbar], [data-ohw-field-type-picker], [data-radix-popper-content-wrapper], [role="menu"], [data-slot="dropdown-menu-content"]'
|
|
23730
|
+
)) {
|
|
23731
|
+
return;
|
|
23732
|
+
}
|
|
21701
23733
|
if (selectedMediaElRef.current && !selectedMediaElRef.current.contains(target) && !target.closest("[data-ohw-media-overlay], [data-ohw-edit-chrome], [data-ohw-item-interaction]")) {
|
|
21702
23734
|
clearMediaSelectionRef.current();
|
|
21703
23735
|
}
|
|
@@ -21718,13 +23750,6 @@ function OhhwellsBridge() {
|
|
|
21718
23750
|
return;
|
|
21719
23751
|
}
|
|
21720
23752
|
}
|
|
21721
|
-
if (isInsideFloatingPanel(target)) return;
|
|
21722
|
-
if (target.closest("[data-ohw-form-toolbar]")) return;
|
|
21723
|
-
if (target.closest(
|
|
21724
|
-
'[data-ohw-field-toolbar], [data-ohw-field-type-picker], [data-radix-popper-content-wrapper], [role="menu"], [data-slot="dropdown-menu-content"]'
|
|
21725
|
-
)) {
|
|
21726
|
-
return;
|
|
21727
|
-
}
|
|
21728
23753
|
{
|
|
21729
23754
|
const formEl = getFormElement(target);
|
|
21730
23755
|
const onSuccessText = target.closest(`[${SUCCESS_TEXT_ATTR}]`);
|
|
@@ -21888,14 +23913,6 @@ function OhhwellsBridge() {
|
|
|
21888
23913
|
}
|
|
21889
23914
|
const clickedButton = findClosestButtonLike(target);
|
|
21890
23915
|
const buttonOnMedia = Boolean(clickedButton && isMediaEditable(editable) && editable.contains(clickedButton));
|
|
21891
|
-
console.log("[click-debug]", {
|
|
21892
|
-
editableType: editable.dataset.ohwEditable,
|
|
21893
|
-
editableTag: editable.tagName,
|
|
21894
|
-
targetTag: target.tagName,
|
|
21895
|
-
clickedButtonTag: clickedButton?.tagName ?? null,
|
|
21896
|
-
buttonOnMedia,
|
|
21897
|
-
isMediaEditableEditable: isMediaEditable(editable)
|
|
21898
|
-
});
|
|
21899
23916
|
if (isMediaEditable(editable) && !buttonOnMedia) {
|
|
21900
23917
|
e.preventDefault();
|
|
21901
23918
|
e.stopPropagation();
|
|
@@ -21930,11 +23947,6 @@ function OhhwellsBridge() {
|
|
|
21930
23947
|
const hrefLookupTarget = buttonOnMedia ? clickedButton : editable;
|
|
21931
23948
|
const hrefCtx = getHrefKeyFromElement(hrefLookupTarget);
|
|
21932
23949
|
const navAnchor = hrefCtx ? getNavigationItemAnchor(hrefCtx.anchor) : null;
|
|
21933
|
-
console.log("[click-debug 2]", {
|
|
21934
|
-
hrefLookupTargetTag: hrefLookupTarget.tagName,
|
|
21935
|
-
hrefCtx: hrefCtx ? { key: hrefCtx.key } : null,
|
|
21936
|
-
navAnchorTag: navAnchor?.tagName ?? null
|
|
21937
|
-
});
|
|
21938
23950
|
if (navAnchor) {
|
|
21939
23951
|
e.preventDefault();
|
|
21940
23952
|
e.stopPropagation();
|
|
@@ -22117,6 +24129,9 @@ function OhhwellsBridge() {
|
|
|
22117
24129
|
setHoveredItemRect(null);
|
|
22118
24130
|
hoveredNavContainerRef.current = null;
|
|
22119
24131
|
setHoveredNavContainerRect(null);
|
|
24132
|
+
siblingHintElRef.current = null;
|
|
24133
|
+
setSiblingHintRect(null);
|
|
24134
|
+
setSiblingHintRects([]);
|
|
22120
24135
|
return;
|
|
22121
24136
|
}
|
|
22122
24137
|
{
|
|
@@ -22237,7 +24252,6 @@ function OhhwellsBridge() {
|
|
|
22237
24252
|
hoveredNavContainerRef.current = null;
|
|
22238
24253
|
setHoveredNavContainerRect(null);
|
|
22239
24254
|
hoveredItemElRef.current = editable;
|
|
22240
|
-
setHoveredItemRect(isSelectedForHoverRef.current(editable) ? null : editable.getBoundingClientRect());
|
|
22241
24255
|
}
|
|
22242
24256
|
}
|
|
22243
24257
|
}
|
|
@@ -22450,6 +24464,20 @@ function OhhwellsBridge() {
|
|
|
22450
24464
|
}
|
|
22451
24465
|
return;
|
|
22452
24466
|
}
|
|
24467
|
+
const navbarCtaHit = findNavbarCtaAtPoint(x, y);
|
|
24468
|
+
if (navbarCtaHit) {
|
|
24469
|
+
hoveredNavContainerRef.current = null;
|
|
24470
|
+
setHoveredNavContainerRect(null);
|
|
24471
|
+
if (selected !== navbarCtaHit && !selected?.contains(navbarCtaHit)) {
|
|
24472
|
+
clearHrefKeyHover(navbarCtaHit);
|
|
24473
|
+
hoveredItemElRef.current = navbarCtaHit;
|
|
24474
|
+
setHoveredItemRect(navbarCtaHit.getBoundingClientRect());
|
|
24475
|
+
} else if (hoveredItemElRef.current === navbarCtaHit) {
|
|
24476
|
+
hoveredItemElRef.current = null;
|
|
24477
|
+
setHoveredItemRect(null);
|
|
24478
|
+
}
|
|
24479
|
+
return;
|
|
24480
|
+
}
|
|
22453
24481
|
const navContainers = Array.from(
|
|
22454
24482
|
document.querySelectorAll("[data-ohw-nav-container]")
|
|
22455
24483
|
);
|
|
@@ -22541,7 +24569,7 @@ function OhhwellsBridge() {
|
|
|
22541
24569
|
};
|
|
22542
24570
|
const probeImageAt = (clientX, clientY, isDragOver = false, fromParentViewport = false) => {
|
|
22543
24571
|
syncSelectedMediaPointerRelease(true);
|
|
22544
|
-
if (linkPopoverOpenRef.current) {
|
|
24572
|
+
if (linkPopoverOpenRef.current || floatingPanelOpenRef.current && isPointOverFloatingPanel(clientX, clientY)) {
|
|
22545
24573
|
if (hoveredImageRef.current) {
|
|
22546
24574
|
hoveredImageRef.current = null;
|
|
22547
24575
|
hoveredImageHasTextOverlapRef.current = false;
|
|
@@ -22552,6 +24580,24 @@ function OhhwellsBridge() {
|
|
|
22552
24580
|
return;
|
|
22553
24581
|
}
|
|
22554
24582
|
const { x, y } = toProbeCoords(clientX, clientY, fromParentViewport);
|
|
24583
|
+
if (!isDragOver) {
|
|
24584
|
+
const buttonHit = findButtonAtPoint(x, y);
|
|
24585
|
+
if (buttonHit) {
|
|
24586
|
+
dismissImageHover();
|
|
24587
|
+
if (findNavbarCtaAtPoint(x, y)) {
|
|
24588
|
+
probeNavigationHoverAt(x, y);
|
|
24589
|
+
return;
|
|
24590
|
+
}
|
|
24591
|
+
document.querySelectorAll("[data-ohw-hovered]").forEach((el) => el.removeAttribute("data-ohw-hovered"));
|
|
24592
|
+
const selected = selectedElRef.current;
|
|
24593
|
+
if (selected !== buttonHit && !selected?.contains(buttonHit)) {
|
|
24594
|
+
clearHrefKeyHover(buttonHit);
|
|
24595
|
+
hoveredItemElRef.current = buttonHit;
|
|
24596
|
+
setHoveredItemRect(buttonHit.getBoundingClientRect());
|
|
24597
|
+
}
|
|
24598
|
+
return;
|
|
24599
|
+
}
|
|
24600
|
+
}
|
|
22555
24601
|
if (isPointOverNavigation(x, y)) {
|
|
22556
24602
|
dismissImageHover();
|
|
22557
24603
|
probeNavigationHoverAt(x, y);
|
|
@@ -22915,7 +24961,11 @@ function OhhwellsBridge() {
|
|
|
22915
24961
|
};
|
|
22916
24962
|
const handleMouseMove = (e) => {
|
|
22917
24963
|
const { clientX, clientY } = e;
|
|
22918
|
-
if (pointOwnedByFloatingPanel(clientX, clientY))
|
|
24964
|
+
if (pointOwnedByFloatingPanel(clientX, clientY)) {
|
|
24965
|
+
dismissImageHover();
|
|
24966
|
+
clearImageHover();
|
|
24967
|
+
return;
|
|
24968
|
+
}
|
|
22919
24969
|
if (isNavDrawerOpen() && isPointOutsideOpenDrawer(clientX, clientY)) {
|
|
22920
24970
|
document.querySelectorAll("[data-ohw-hovered]").forEach((el) => el.removeAttribute("data-ohw-hovered"));
|
|
22921
24971
|
formHoverElRef.current = null;
|
|
@@ -22944,7 +24994,12 @@ function OhhwellsBridge() {
|
|
|
22944
24994
|
setHoveredItemRect(null);
|
|
22945
24995
|
hoveredNavContainerRef.current = null;
|
|
22946
24996
|
setHoveredNavContainerRect(null);
|
|
24997
|
+
siblingHintElRef.current = null;
|
|
24998
|
+
setSiblingHintRect(null);
|
|
24999
|
+
setSiblingHintRects([]);
|
|
22947
25000
|
dismissImageHover();
|
|
25001
|
+
clearImageHover();
|
|
25002
|
+
setSectionGap(null);
|
|
22948
25003
|
return;
|
|
22949
25004
|
}
|
|
22950
25005
|
if (probeSocialsRowAt(clientX, clientY)) return;
|
|
@@ -22956,7 +25011,11 @@ function OhhwellsBridge() {
|
|
|
22956
25011
|
if (e.data?.type !== "ow:pointer-sync") return;
|
|
22957
25012
|
const { clientX, clientY } = e.data;
|
|
22958
25013
|
if (typeof clientX !== "number" || typeof clientY !== "number") return;
|
|
22959
|
-
if (pointOwnedByFloatingPanel(clientX, clientY))
|
|
25014
|
+
if (pointOwnedByFloatingPanel(clientX, clientY)) {
|
|
25015
|
+
dismissImageHover();
|
|
25016
|
+
clearImageHover();
|
|
25017
|
+
return;
|
|
25018
|
+
}
|
|
22960
25019
|
if (isNavDrawerOpen() && isPointOutsideOpenDrawer(clientX, clientY)) return;
|
|
22961
25020
|
if (probeSocialsRowAt(clientX, clientY)) return;
|
|
22962
25021
|
probeSectionGapAt(clientX, clientY);
|
|
@@ -22973,6 +25032,11 @@ function OhhwellsBridge() {
|
|
|
22973
25032
|
return;
|
|
22974
25033
|
}
|
|
22975
25034
|
if (onNavDragOver(e)) return;
|
|
25035
|
+
if (buttonCollectionDragRef.current) {
|
|
25036
|
+
e.preventDefault();
|
|
25037
|
+
if (e.dataTransfer) e.dataTransfer.dropEffect = "move";
|
|
25038
|
+
return;
|
|
25039
|
+
}
|
|
22976
25040
|
e.preventDefault();
|
|
22977
25041
|
const el = findImageAtPoint(e.clientX, e.clientY, false);
|
|
22978
25042
|
if (!el) {
|
|
@@ -22997,6 +25061,7 @@ function OhhwellsBridge() {
|
|
|
22997
25061
|
};
|
|
22998
25062
|
const handleDrop = (e) => {
|
|
22999
25063
|
e.preventDefault();
|
|
25064
|
+
if (buttonCollectionDragRef.current || navDragRef.current || footerDragRef.current) return;
|
|
23000
25065
|
const el = findImageAtPoint(e.clientX, e.clientY, false);
|
|
23001
25066
|
if (!el) return;
|
|
23002
25067
|
const file = e.dataTransfer?.files?.[0];
|
|
@@ -23296,6 +25361,7 @@ function OhhwellsBridge() {
|
|
|
23296
25361
|
}
|
|
23297
25362
|
if (typeof content[STYLE_STORE_KEY] === "string") {
|
|
23298
25363
|
stylesRef.current = content[STYLE_STORE_KEY];
|
|
25364
|
+
document.querySelectorAll('[data-ohw-editable="form"]').forEach((f) => markFormFields(f));
|
|
23299
25365
|
applyStylesToDom(parseStyleStore(content[STYLE_STORE_KEY]));
|
|
23300
25366
|
}
|
|
23301
25367
|
applyBrandChrome(content);
|
|
@@ -23308,12 +25374,12 @@ function OhhwellsBridge() {
|
|
|
23308
25374
|
continue;
|
|
23309
25375
|
}
|
|
23310
25376
|
if (key === AI_SECTIONS_KEY) continue;
|
|
25377
|
+
if (key === LOGO_PLACEHOLDER_KEY) continue;
|
|
25378
|
+
if (LOGO_IMAGE_KEYS.includes(key) && !String(val ?? "").trim()) continue;
|
|
23311
25379
|
if (key === BRAND_KIT_KEY) continue;
|
|
23312
25380
|
if (key === STYLE_STORE_KEY) continue;
|
|
23313
25381
|
if (BRAND_CHROME_KEYS.has(key)) continue;
|
|
23314
|
-
if (key === LOGO_PLACEHOLDER_KEY) continue;
|
|
23315
25382
|
if (key === CUSTOM_CODE_AFTER_HEAD_KEY || key === CUSTOM_CODE_BEFORE_HEAD_KEY) continue;
|
|
23316
|
-
if (LOGO_IMAGE_KEYS.includes(key) && !String(val ?? "").trim()) continue;
|
|
23317
25383
|
if (applyVideoSettingNode(key, val)) continue;
|
|
23318
25384
|
if (applyCarouselNode(key, val)) continue;
|
|
23319
25385
|
document.querySelectorAll(`[data-ohw-key="${key}"]`).forEach((el) => {
|
|
@@ -23352,6 +25418,7 @@ function OhhwellsBridge() {
|
|
|
23352
25418
|
editContentRef.current = { ...editContentRef.current, ...content };
|
|
23353
25419
|
reconcileNavbarItemsFromContent(editContentRef.current);
|
|
23354
25420
|
reconcileFooterOrderFromContent(editContentRef.current);
|
|
25421
|
+
syncButtonsFromContent(document, editContentRef.current);
|
|
23355
25422
|
syncNavigationDragCursorAttrs();
|
|
23356
25423
|
if (typeof content[STYLE_STORE_KEY] === "string") {
|
|
23357
25424
|
applyStylesToDom(parseStyleStore(content[STYLE_STORE_KEY]));
|
|
@@ -23758,6 +25825,12 @@ function OhhwellsBridge() {
|
|
|
23758
25825
|
closeLinkPopoverRef.current();
|
|
23759
25826
|
return;
|
|
23760
25827
|
}
|
|
25828
|
+
if (floatingPanelOpenRef.current) {
|
|
25829
|
+
setFloatingPanelRef.current(null);
|
|
25830
|
+
deselectRef.current();
|
|
25831
|
+
deactivateRef.current();
|
|
25832
|
+
return;
|
|
25833
|
+
}
|
|
23761
25834
|
deselectRef.current();
|
|
23762
25835
|
deactivateRef.current();
|
|
23763
25836
|
clearMediaSelectionRef.current();
|
|
@@ -24056,8 +26129,12 @@ function OhhwellsBridge() {
|
|
|
24056
26129
|
if (inserted) {
|
|
24057
26130
|
const tracker = getSectionsTracker();
|
|
24058
26131
|
postToParentRef.current({ type: "ow:change", nodes: [{ key: "__ohw_sections", text: tracker.textContent ?? "[]" }] });
|
|
24059
|
-
const
|
|
24060
|
-
|
|
26132
|
+
const reportHeight = () => {
|
|
26133
|
+
const h = document.body.scrollHeight;
|
|
26134
|
+
if (h > 50) postToParentRef.current({ type: "ow:height", height: h });
|
|
26135
|
+
};
|
|
26136
|
+
reportHeight();
|
|
26137
|
+
setTimeout(reportHeight, 500);
|
|
24061
26138
|
}
|
|
24062
26139
|
};
|
|
24063
26140
|
const handleSwitchSchedule = (e) => {
|
|
@@ -24261,11 +26338,8 @@ function OhhwellsBridge() {
|
|
|
24261
26338
|
};
|
|
24262
26339
|
const handleParentScroll = (e) => {
|
|
24263
26340
|
if (e.data?.type !== "ow:parent-scroll") return;
|
|
24264
|
-
const { iframeOffsetTop, headerH, canvasH } = e.data;
|
|
24265
|
-
parentScrollRef.current = { iframeOffsetTop, headerH, canvasH };
|
|
24266
|
-
if (floatingPanelOpenRef.current) {
|
|
24267
|
-
setParentScrollSnap({ iframeOffsetTop, headerH, canvasH });
|
|
24268
|
-
}
|
|
26341
|
+
const { iframeOffsetTop, headerH, canvasH, promptBarH = 0 } = e.data;
|
|
26342
|
+
parentScrollRef.current = { iframeOffsetTop, headerH, canvasH, promptBarH };
|
|
24269
26343
|
if (visibleViewportRef.current) {
|
|
24270
26344
|
applyVisibleViewport(visibleViewportRef.current, parentScrollRef.current);
|
|
24271
26345
|
}
|
|
@@ -24489,10 +26563,10 @@ function OhhwellsBridge() {
|
|
|
24489
26563
|
window.removeEventListener("message", handleDeleteSection);
|
|
24490
26564
|
window.removeEventListener("message", handleDuplicateSection);
|
|
24491
26565
|
window.removeEventListener("message", handleDeactivate);
|
|
24492
|
-
document.documentElement.removeAttribute("data-ohw-panel-dragging");
|
|
24493
26566
|
window.removeEventListener("message", handleToastAction);
|
|
24494
26567
|
window.removeEventListener("message", handleFormCount);
|
|
24495
26568
|
window.removeEventListener("message", handleUiEscape);
|
|
26569
|
+
document.documentElement.removeAttribute("data-ohw-panel-dragging");
|
|
24496
26570
|
autoSaveTimers.current.forEach(clearTimeout);
|
|
24497
26571
|
autoSaveTimers.current.clear();
|
|
24498
26572
|
if (imageUnhoverTimerRef.current) clearTimeout(imageUnhoverTimerRef.current);
|
|
@@ -24655,6 +26729,97 @@ function OhhwellsBridge() {
|
|
|
24655
26729
|
unlockFooterDragInteraction();
|
|
24656
26730
|
};
|
|
24657
26731
|
}, [isEditMode]);
|
|
26732
|
+
useEffect15(() => {
|
|
26733
|
+
if (!isEditMode) return;
|
|
26734
|
+
const THRESHOLD = 10;
|
|
26735
|
+
const onPointerDown = (e) => {
|
|
26736
|
+
if (e.button !== 0) return;
|
|
26737
|
+
if (buttonCollectionDragRef.current || navDragRef.current || footerDragRef.current) return;
|
|
26738
|
+
if (buttonPointerDragRef.current) return;
|
|
26739
|
+
const target = e.target;
|
|
26740
|
+
if (!target) return;
|
|
26741
|
+
if (target.closest(
|
|
26742
|
+
'[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]'
|
|
26743
|
+
)) {
|
|
26744
|
+
return;
|
|
26745
|
+
}
|
|
26746
|
+
const fromTarget = target.closest('[data-ohw-role="navbar-button"]');
|
|
26747
|
+
const anchor = (fromTarget && !fromTarget.closest("[data-ohw-bridge]") ? fromTarget : null) ?? findNavbarCtaAtPoint(e.clientX, e.clientY);
|
|
26748
|
+
if (!anchor || !collectionDragEnabled(anchor)) return;
|
|
26749
|
+
disableNativeHrefDrag(anchor);
|
|
26750
|
+
setMediaHover(null);
|
|
26751
|
+
buttonPointerDragRef.current = {
|
|
26752
|
+
el: anchor,
|
|
26753
|
+
startX: e.clientX,
|
|
26754
|
+
startY: e.clientY,
|
|
26755
|
+
pointerId: e.pointerId,
|
|
26756
|
+
started: false
|
|
26757
|
+
};
|
|
26758
|
+
};
|
|
26759
|
+
const onPointerMove = (e) => {
|
|
26760
|
+
const pending = buttonPointerDragRef.current;
|
|
26761
|
+
if (!pending) return;
|
|
26762
|
+
if (pending.started) {
|
|
26763
|
+
e.preventDefault();
|
|
26764
|
+
clearTextSelection();
|
|
26765
|
+
const dragged = buttonCollectionDragRef.current;
|
|
26766
|
+
if (!dragged) return;
|
|
26767
|
+
refreshButtonDragVisuals(dragged, e.clientX, e.clientY);
|
|
26768
|
+
return;
|
|
26769
|
+
}
|
|
26770
|
+
const dx = e.clientX - pending.startX;
|
|
26771
|
+
const dy = e.clientY - pending.startY;
|
|
26772
|
+
if (dx * dx + dy * dy < THRESHOLD * THRESHOLD) return;
|
|
26773
|
+
e.preventDefault();
|
|
26774
|
+
pending.started = true;
|
|
26775
|
+
armFooterPressDrag();
|
|
26776
|
+
clearTextSelection();
|
|
26777
|
+
try {
|
|
26778
|
+
document.body.setPointerCapture(pending.pointerId);
|
|
26779
|
+
} catch {
|
|
26780
|
+
}
|
|
26781
|
+
if (linkPopoverOpenRef.current) setLinkPopoverRef.current(null);
|
|
26782
|
+
if (activeElRef.current) deactivateRef.current();
|
|
26783
|
+
ensureNavbarButtonCollection(pending.el, editContentRef.current);
|
|
26784
|
+
buttonCollectionDragRef.current = pending.el;
|
|
26785
|
+
lockFooterDuringDrag();
|
|
26786
|
+
setIsItemDragging(true);
|
|
26787
|
+
refreshButtonDragVisuals(pending.el, e.clientX, e.clientY);
|
|
26788
|
+
};
|
|
26789
|
+
const endPointerDrag = (e) => {
|
|
26790
|
+
const pending = buttonPointerDragRef.current;
|
|
26791
|
+
buttonPointerDragRef.current = null;
|
|
26792
|
+
try {
|
|
26793
|
+
if (document.body.hasPointerCapture(e.pointerId)) {
|
|
26794
|
+
document.body.releasePointerCapture(e.pointerId);
|
|
26795
|
+
}
|
|
26796
|
+
} catch {
|
|
26797
|
+
}
|
|
26798
|
+
if (!pending) return;
|
|
26799
|
+
if (!pending.started) {
|
|
26800
|
+
unlockFooterDragInteraction();
|
|
26801
|
+
return;
|
|
26802
|
+
}
|
|
26803
|
+
suppressNextClickRef.current = true;
|
|
26804
|
+
suppressClickUntilRef.current = Date.now() + 500;
|
|
26805
|
+
persistButtonCollectionDrag(pending.el, e.clientX);
|
|
26806
|
+
};
|
|
26807
|
+
const blockSelectStart = (e) => {
|
|
26808
|
+
if (buttonCollectionDragRef.current || buttonPointerDragRef.current?.started) e.preventDefault();
|
|
26809
|
+
};
|
|
26810
|
+
document.addEventListener("pointerdown", onPointerDown, true);
|
|
26811
|
+
document.addEventListener("pointermove", onPointerMove, true);
|
|
26812
|
+
document.addEventListener("pointerup", endPointerDrag, true);
|
|
26813
|
+
document.addEventListener("pointercancel", endPointerDrag, true);
|
|
26814
|
+
document.addEventListener("selectstart", blockSelectStart, true);
|
|
26815
|
+
return () => {
|
|
26816
|
+
document.removeEventListener("pointerdown", onPointerDown, true);
|
|
26817
|
+
document.removeEventListener("pointermove", onPointerMove, true);
|
|
26818
|
+
document.removeEventListener("pointerup", endPointerDrag, true);
|
|
26819
|
+
document.removeEventListener("pointercancel", endPointerDrag, true);
|
|
26820
|
+
document.removeEventListener("selectstart", blockSelectStart, true);
|
|
26821
|
+
};
|
|
26822
|
+
}, [isEditMode, persistButtonCollectionDrag, refreshButtonDragVisuals]);
|
|
24658
26823
|
useEffect15(() => {
|
|
24659
26824
|
const handler = (e) => {
|
|
24660
26825
|
if (e.data?.type !== "ow:request-schedule-config") return;
|
|
@@ -24695,7 +26860,7 @@ function OhhwellsBridge() {
|
|
|
24695
26860
|
postToParent2({
|
|
24696
26861
|
type: "ow:ready",
|
|
24697
26862
|
version: "1",
|
|
24698
|
-
bridgeVersion: "0.1.
|
|
26863
|
+
bridgeVersion: "0.1.122",
|
|
24699
26864
|
path: pathname,
|
|
24700
26865
|
nodes: collectEditableNodes(editContentRef.current),
|
|
24701
26866
|
sections
|
|
@@ -24774,12 +26939,12 @@ function OhhwellsBridge() {
|
|
|
24774
26939
|
return;
|
|
24775
26940
|
}
|
|
24776
26941
|
if (type !== "ow:logo-size-set") return;
|
|
24777
|
-
const
|
|
24778
|
-
if (!Number.isFinite(
|
|
24779
|
-
const next = editorViewport === "mobile" ? { ...logoSizeDraft, mobilePx:
|
|
26942
|
+
const px2 = Number(e.data.px);
|
|
26943
|
+
if (!Number.isFinite(px2)) return;
|
|
26944
|
+
const next = editorViewport === "mobile" ? { ...logoSizeDraft, mobilePx: px2, mobileFollowing: false } : {
|
|
24780
26945
|
...logoSizeDraft,
|
|
24781
|
-
desktopPx:
|
|
24782
|
-
mobilePx: logoSizeDraft.mobileFollowing ?
|
|
26946
|
+
desktopPx: px2,
|
|
26947
|
+
mobilePx: logoSizeDraft.mobileFollowing ? px2 : logoSizeDraft.mobilePx
|
|
24783
26948
|
};
|
|
24784
26949
|
setLogoSizeDraft(next);
|
|
24785
26950
|
persistLogoSizeDraft(session.placement, next);
|
|
@@ -24877,6 +27042,36 @@ function OhhwellsBridge() {
|
|
|
24877
27042
|
const handleDuplicateSelected = useCallback10(() => {
|
|
24878
27043
|
const selected = selectedElRef.current;
|
|
24879
27044
|
if (!selected || !isNavigationItem2(selected)) return;
|
|
27045
|
+
if (isCtaButton(selected)) {
|
|
27046
|
+
const id = buttonId(selected);
|
|
27047
|
+
if (!id) return;
|
|
27048
|
+
const tokens = tokensForButton(selected, true);
|
|
27049
|
+
if (!readAssignments(editContentRef.current)[id]) {
|
|
27050
|
+
const assignment = assignmentFor(selected, editContentRef.current, tokens);
|
|
27051
|
+
const assignments = withAssignment(editContentRef.current, id, assignment);
|
|
27052
|
+
editContentRef.current = {
|
|
27053
|
+
...editContentRef.current,
|
|
27054
|
+
[BUTTON_ASSIGNMENTS_KEY]: JSON.stringify(assignments)
|
|
27055
|
+
};
|
|
27056
|
+
applyButtonStyle(selected, assignment, tokens);
|
|
27057
|
+
}
|
|
27058
|
+
const result = duplicateButton(selected, editContentRef.current);
|
|
27059
|
+
if (!result) return;
|
|
27060
|
+
editContentRef.current = result.content;
|
|
27061
|
+
const copyHref = result.copy.getAttribute("data-ohw-href-key");
|
|
27062
|
+
const copyHrefVal = copyHref ? result.content[copyHref] : void 0;
|
|
27063
|
+
if (copyHref && copyHrefVal !== void 0) applyLinkByKey(copyHref, copyHrefVal);
|
|
27064
|
+
postToParent2({ type: "ow:change", nodes: result.nodes });
|
|
27065
|
+
enforceLinkHrefs();
|
|
27066
|
+
requestAnimationFrame(() => {
|
|
27067
|
+
selectRef.current(result.copy);
|
|
27068
|
+
requestAnimationFrame(() => {
|
|
27069
|
+
const el = selectedElRef.current;
|
|
27070
|
+
if (el?.isConnected) setToolbarRect(el.getBoundingClientRect());
|
|
27071
|
+
});
|
|
27072
|
+
});
|
|
27073
|
+
return;
|
|
27074
|
+
}
|
|
24880
27075
|
const hrefKey = selected.getAttribute("data-ohw-href-key");
|
|
24881
27076
|
if (!hrefKey) return;
|
|
24882
27077
|
const social = getSocialItem(selected);
|
|
@@ -25006,7 +27201,7 @@ function OhhwellsBridge() {
|
|
|
25006
27201
|
selectRef.current(result.anchor);
|
|
25007
27202
|
});
|
|
25008
27203
|
}
|
|
25009
|
-
}, [postToParent2]);
|
|
27204
|
+
}, [postToParent2, tokensForButton]);
|
|
25010
27205
|
const runPendingDeleteUndo = useCallback10(() => {
|
|
25011
27206
|
const pending = pendingDeleteUndoRef.current;
|
|
25012
27207
|
if (!pending) return false;
|
|
@@ -25018,6 +27213,38 @@ function OhhwellsBridge() {
|
|
|
25018
27213
|
const handleDeleteSelected = useCallback10(() => {
|
|
25019
27214
|
const selected = selectedElRef.current;
|
|
25020
27215
|
if (!selected) return false;
|
|
27216
|
+
if (isCtaButton(selected)) {
|
|
27217
|
+
if (!canDeleteButton(selected)) return false;
|
|
27218
|
+
const previousContent = editContentRef.current;
|
|
27219
|
+
const result = deleteButton(selected, previousContent);
|
|
27220
|
+
if (!result) return false;
|
|
27221
|
+
editContentRef.current = result.content;
|
|
27222
|
+
postToParent2({ type: "ow:change", nodes: result.nodes });
|
|
27223
|
+
const actionId = typeof crypto !== "undefined" && "randomUUID" in crypto ? crypto.randomUUID() : `delete-${Date.now()}`;
|
|
27224
|
+
const restoreNodes = result.nodes.map((node) => ({
|
|
27225
|
+
key: node.key,
|
|
27226
|
+
text: previousContent[node.key] ?? ""
|
|
27227
|
+
}));
|
|
27228
|
+
pendingDeleteUndoRef.current = {
|
|
27229
|
+
actionId,
|
|
27230
|
+
restore: () => {
|
|
27231
|
+
result.undo();
|
|
27232
|
+
editContentRef.current = { ...editContentRef.current, ...Object.fromEntries(restoreNodes.map((node) => [node.key, node.text])) };
|
|
27233
|
+
postToParent2({ type: "ow:change", nodes: restoreNodes });
|
|
27234
|
+
syncButtonsFromContent(document, editContentRef.current);
|
|
27235
|
+
}
|
|
27236
|
+
};
|
|
27237
|
+
deselectRef.current();
|
|
27238
|
+
postToParent2({
|
|
27239
|
+
type: "ow:toast",
|
|
27240
|
+
title: "Button deleted",
|
|
27241
|
+
toastType: "success",
|
|
27242
|
+
actionLabel: "Undo",
|
|
27243
|
+
actionId,
|
|
27244
|
+
duration: 6e3
|
|
27245
|
+
});
|
|
27246
|
+
return true;
|
|
27247
|
+
}
|
|
25021
27248
|
return deleteSelectedNavFooterItem({
|
|
25022
27249
|
selected,
|
|
25023
27250
|
isTextEditing: Boolean(activeElRef.current),
|
|
@@ -25155,14 +27382,14 @@ function OhhwellsBridge() {
|
|
|
25155
27382
|
},
|
|
25156
27383
|
[postToParent2]
|
|
25157
27384
|
);
|
|
25158
|
-
return /* @__PURE__ */
|
|
25159
|
-
/* @__PURE__ */
|
|
25160
|
-
/* @__PURE__ */
|
|
25161
|
-
subdomain && !isEditMode && showBranding && /* @__PURE__ */
|
|
27385
|
+
return /* @__PURE__ */ jsxs23(Fragment10, { children: [
|
|
27386
|
+
/* @__PURE__ */ jsx36("div", { id: "ohw-loader", suppressHydrationWarning: true, style: { ...OHW_LOADER_STYLE, display: "none" }, children: /* @__PURE__ */ jsx36(OhwLoaderSpinner, {}) }),
|
|
27387
|
+
/* @__PURE__ */ jsx36("script", { suppressHydrationWarning: true, dangerouslySetInnerHTML: { __html: OHW_LOADER_PREHYDRATE_SCRIPT } }),
|
|
27388
|
+
subdomain && !isEditMode && showBranding && /* @__PURE__ */ jsx36(MadeWithOhhWells, {}),
|
|
25162
27389
|
bridgeRoot ? createPortal3(
|
|
25163
|
-
/* @__PURE__ */
|
|
25164
|
-
/* @__PURE__ */
|
|
25165
|
-
isEditMode && /* @__PURE__ */
|
|
27390
|
+
/* @__PURE__ */ jsxs23(Fragment10, { children: [
|
|
27391
|
+
/* @__PURE__ */ jsx36("div", { ref: attachVisibleViewport, "data-ohw-visible-viewport": "", "aria-hidden": true }),
|
|
27392
|
+
isEditMode && /* @__PURE__ */ jsx36(
|
|
25166
27393
|
AiSectionOverlay,
|
|
25167
27394
|
{
|
|
25168
27395
|
postToParent: postToParent2,
|
|
@@ -25170,7 +27397,7 @@ function OhhwellsBridge() {
|
|
|
25170
27397
|
onSelectionChange: handleAiSectionSelectionChange
|
|
25171
27398
|
}
|
|
25172
27399
|
),
|
|
25173
|
-
isEditMode && /* @__PURE__ */
|
|
27400
|
+
isEditMode && /* @__PURE__ */ jsx36(
|
|
25174
27401
|
AiMediaStripOverlay,
|
|
25175
27402
|
{
|
|
25176
27403
|
postToParent: postToParent2,
|
|
@@ -25179,7 +27406,7 @@ function OhhwellsBridge() {
|
|
|
25179
27406
|
clearInteractionChromeRef
|
|
25180
27407
|
}
|
|
25181
27408
|
),
|
|
25182
|
-
isEditMode && /* @__PURE__ */
|
|
27409
|
+
isEditMode && /* @__PURE__ */ jsx36(
|
|
25183
27410
|
AiPricingCardOverlay,
|
|
25184
27411
|
{
|
|
25185
27412
|
postToParent: postToParent2,
|
|
@@ -25187,12 +27414,12 @@ function OhhwellsBridge() {
|
|
|
25187
27414
|
applyTreeLocalRef
|
|
25188
27415
|
}
|
|
25189
27416
|
),
|
|
25190
|
-
isSectionDragging && sectionDropSlots.map((slot, i) => /* @__PURE__ */
|
|
27417
|
+
isSectionDragging && sectionDropSlots.map((slot, i) => /* @__PURE__ */ jsx36(
|
|
25191
27418
|
"div",
|
|
25192
27419
|
{
|
|
25193
27420
|
className: "pointer-events-none fixed z-2147483646",
|
|
25194
27421
|
style: { left: slot.left, top: slot.y, width: slot.width, height: 3, transform: "translateY(-50%)" },
|
|
25195
|
-
children: /* @__PURE__ */
|
|
27422
|
+
children: /* @__PURE__ */ jsx36(
|
|
25196
27423
|
DropIndicator,
|
|
25197
27424
|
{
|
|
25198
27425
|
direction: "horizontal",
|
|
@@ -25203,7 +27430,7 @@ function OhhwellsBridge() {
|
|
|
25203
27430
|
},
|
|
25204
27431
|
`section-drop-${slot.insertIndex}-${i}`
|
|
25205
27432
|
)),
|
|
25206
|
-
Object.entries(uploadingRects).map(([key, { rect, fadingOut }]) => /* @__PURE__ */
|
|
27433
|
+
Object.entries(uploadingRects).map(([key, { rect, fadingOut }]) => /* @__PURE__ */ jsx36(
|
|
25207
27434
|
MediaOverlay,
|
|
25208
27435
|
{
|
|
25209
27436
|
hover: { key, rect, elementType: "image", isDragOver: false, hasTextOverlap: false },
|
|
@@ -25214,7 +27441,7 @@ function OhhwellsBridge() {
|
|
|
25214
27441
|
},
|
|
25215
27442
|
`uploading-${key}`
|
|
25216
27443
|
)),
|
|
25217
|
-
mediaHover && !(mediaHover.key in uploadingRects) && mediaHover.key !== selectedMedia?.key && /* @__PURE__ */
|
|
27444
|
+
mediaHover && !(mediaHover.key in uploadingRects) && mediaHover.key !== selectedMedia?.key && /* @__PURE__ */ jsx36(
|
|
25218
27445
|
MediaOverlay,
|
|
25219
27446
|
{
|
|
25220
27447
|
hover: mediaHover,
|
|
@@ -25225,7 +27452,7 @@ function OhhwellsBridge() {
|
|
|
25225
27452
|
onVideoSettingsChange: handleVideoSettingsChange
|
|
25226
27453
|
}
|
|
25227
27454
|
),
|
|
25228
|
-
selectedMedia && !(selectedMedia.key in uploadingRects) && !linkPopover && /* @__PURE__ */
|
|
27455
|
+
selectedMedia && !(selectedMedia.key in uploadingRects) && !linkPopover && /* @__PURE__ */ jsx36(
|
|
25229
27456
|
MediaOverlay,
|
|
25230
27457
|
{
|
|
25231
27458
|
hover: selectedMedia,
|
|
@@ -25237,7 +27464,7 @@ function OhhwellsBridge() {
|
|
|
25237
27464
|
onVideoSettingsChange: handleVideoSettingsChange
|
|
25238
27465
|
}
|
|
25239
27466
|
),
|
|
25240
|
-
carouselHover && !linkPopover && !isItemDragging && /* @__PURE__ */
|
|
27467
|
+
carouselHover && !linkPopover && !isItemDragging && /* @__PURE__ */ jsx36(
|
|
25241
27468
|
CarouselOverlay,
|
|
25242
27469
|
{
|
|
25243
27470
|
hover: carouselHover,
|
|
@@ -25245,10 +27472,10 @@ function OhhwellsBridge() {
|
|
|
25245
27472
|
cueOnly: !!carouselHover.fullBleedSectionId && carouselHover.fullBleedSectionId !== selectedAiSectionId
|
|
25246
27473
|
}
|
|
25247
27474
|
),
|
|
25248
|
-
siblingHintRect && !linkPopover && !isItemDragging && siblingHintRects.length === 0 && /* @__PURE__ */
|
|
25249
|
-
siblingHintRects.length > 0 && !linkPopover && !isItemDragging && siblingHintRects.map((rect, i) => /* @__PURE__ */
|
|
25250
|
-
isItemDragging && draggedItemRect && selectedElRef.current !== footerDragRef.current?.draggedEl && selectedElRef.current !== navDragRef.current?.draggedEl && /* @__PURE__ */
|
|
25251
|
-
isItemDragging && footerDropSlots.map((slot, i) => /* @__PURE__ */
|
|
27475
|
+
siblingHintRect && !linkPopover && !isItemDragging && siblingHintRects.length === 0 && /* @__PURE__ */ jsx36(ItemInteractionLayer, { rect: siblingHintRect, state: "sibling-hint" }),
|
|
27476
|
+
siblingHintRects.length > 0 && !linkPopover && !isItemDragging && siblingHintRects.map((rect, i) => /* @__PURE__ */ jsx36(ItemInteractionLayer, { rect, state: "sibling-hint" }, `sibling-hint-${i}`)),
|
|
27477
|
+
isItemDragging && draggedItemRect && selectedElRef.current !== footerDragRef.current?.draggedEl && selectedElRef.current !== navDragRef.current?.draggedEl && selectedElRef.current !== buttonCollectionDragRef.current && /* @__PURE__ */ jsx36(ItemInteractionLayer, { rect: draggedItemRect, state: "dragging" }),
|
|
27478
|
+
isItemDragging && footerDropSlots.map((slot, i) => /* @__PURE__ */ jsx36(
|
|
25252
27479
|
"div",
|
|
25253
27480
|
{
|
|
25254
27481
|
className: "pointer-events-none fixed z-2147483646",
|
|
@@ -25258,7 +27485,7 @@ function OhhwellsBridge() {
|
|
|
25258
27485
|
width: slot.width,
|
|
25259
27486
|
height: slot.height
|
|
25260
27487
|
},
|
|
25261
|
-
children: /* @__PURE__ */
|
|
27488
|
+
children: /* @__PURE__ */ jsx36(
|
|
25262
27489
|
DropIndicator,
|
|
25263
27490
|
{
|
|
25264
27491
|
direction: slot.direction,
|
|
@@ -25269,7 +27496,7 @@ function OhhwellsBridge() {
|
|
|
25269
27496
|
},
|
|
25270
27497
|
`footer-drop-${slot.direction}-${slot.columnIndex}-${slot.insertIndex}-${i}`
|
|
25271
27498
|
)),
|
|
25272
|
-
isItemDragging && navDropSlots.map((slot, i) => /* @__PURE__ */
|
|
27499
|
+
isItemDragging && navDropSlots.map((slot, i) => /* @__PURE__ */ jsx36(
|
|
25273
27500
|
"div",
|
|
25274
27501
|
{
|
|
25275
27502
|
className: "pointer-events-none fixed z-2147483646",
|
|
@@ -25279,7 +27506,7 @@ function OhhwellsBridge() {
|
|
|
25279
27506
|
width: slot.width,
|
|
25280
27507
|
height: slot.height
|
|
25281
27508
|
},
|
|
25282
|
-
children: /* @__PURE__ */
|
|
27509
|
+
children: /* @__PURE__ */ jsx36(
|
|
25283
27510
|
DropIndicator,
|
|
25284
27511
|
{
|
|
25285
27512
|
direction: slot.direction,
|
|
@@ -25290,10 +27517,31 @@ function OhhwellsBridge() {
|
|
|
25290
27517
|
},
|
|
25291
27518
|
`nav-drop-${slot.direction}-${slot.parentId ?? "root"}-${slot.insertIndex}-${i}`
|
|
25292
27519
|
)),
|
|
25293
|
-
|
|
25294
|
-
|
|
25295
|
-
|
|
25296
|
-
|
|
27520
|
+
isItemDragging && buttonDropSlots.map((slot, i) => /* @__PURE__ */ jsx36(
|
|
27521
|
+
"div",
|
|
27522
|
+
{
|
|
27523
|
+
className: "pointer-events-none fixed z-2147483646",
|
|
27524
|
+
style: {
|
|
27525
|
+
left: slot.left,
|
|
27526
|
+
top: slot.top,
|
|
27527
|
+
width: slot.width,
|
|
27528
|
+
height: slot.height
|
|
27529
|
+
},
|
|
27530
|
+
children: /* @__PURE__ */ jsx36(
|
|
27531
|
+
DropIndicator,
|
|
27532
|
+
{
|
|
27533
|
+
direction: slot.direction,
|
|
27534
|
+
state: activeButtonDropIndex === i ? "dragActive" : "dragIdle",
|
|
27535
|
+
className: "!h-full !w-full"
|
|
27536
|
+
}
|
|
27537
|
+
)
|
|
27538
|
+
},
|
|
27539
|
+
`button-drop-${slot.direction}-${slot.insertIndex}-${i}`
|
|
27540
|
+
)),
|
|
27541
|
+
hoveredNavContainerRect && (toolbarVariant !== "select-frame" || isFooterFrameSelection) && !linkPopover && !isItemDragging && /* @__PURE__ */ jsx36(ItemInteractionLayer, { rect: hoveredNavContainerRect, state: "hover" }),
|
|
27542
|
+
hoveredItemRect && !linkPopover && !hoveredNavContainerRect && !isItemDragging && hoveredItemElRef.current !== selectedElRef.current && /* @__PURE__ */ jsx36(ItemInteractionLayer, { rect: hoveredItemRect, state: "hover" }),
|
|
27543
|
+
hoveredTextRect && !hoveredNavContainerRect && !hoveredItemRect && !isItemDragging && toolbarVariant !== "rich-text" && /* @__PURE__ */ jsx36(ItemInteractionLayer, { rect: hoveredTextRect, state: "hover" }),
|
|
27544
|
+
formPickRect && !isItemDragging && /* @__PURE__ */ jsx36(
|
|
25297
27545
|
ItemInteractionLayer,
|
|
25298
27546
|
{
|
|
25299
27547
|
rect: formPickRect,
|
|
@@ -25301,13 +27549,13 @@ function OhhwellsBridge() {
|
|
|
25301
27549
|
itemDragSurface: false,
|
|
25302
27550
|
toolbarAlign: "left",
|
|
25303
27551
|
chromeGap: 24,
|
|
25304
|
-
toolbar: fieldPickRect ? void 0 : /* @__PURE__ */
|
|
27552
|
+
toolbar: fieldPickRect ? void 0 : /* @__PURE__ */ jsxs23(
|
|
25305
27553
|
"div",
|
|
25306
27554
|
{
|
|
25307
27555
|
"data-ohw-form-toolbar": "",
|
|
25308
27556
|
className: "pointer-events-auto flex items-center gap-0.5 whitespace-nowrap rounded-lg border border-border bg-background p-1 shadow-md",
|
|
25309
27557
|
children: [
|
|
25310
|
-
/* @__PURE__ */
|
|
27558
|
+
/* @__PURE__ */ jsx36(
|
|
25311
27559
|
"button",
|
|
25312
27560
|
{
|
|
25313
27561
|
type: "button",
|
|
@@ -25315,11 +27563,11 @@ function OhhwellsBridge() {
|
|
|
25315
27563
|
className: "flex h-7 w-7 items-center justify-center rounded-md text-foreground transition-colors hover:bg-muted/80",
|
|
25316
27564
|
onClick: () => setFieldTypePickerOpen((open) => !open),
|
|
25317
27565
|
"data-ohw-add-field": "",
|
|
25318
|
-
children: /* @__PURE__ */
|
|
27566
|
+
children: /* @__PURE__ */ jsx36(Plus4, { size: 15, "aria-hidden": true })
|
|
25319
27567
|
}
|
|
25320
27568
|
),
|
|
25321
|
-
/* @__PURE__ */
|
|
25322
|
-
/* @__PURE__ */
|
|
27569
|
+
/* @__PURE__ */ jsx36("div", { className: "mx-0.5 h-5 w-px bg-border" }),
|
|
27570
|
+
/* @__PURE__ */ jsxs23(
|
|
25323
27571
|
"button",
|
|
25324
27572
|
{
|
|
25325
27573
|
type: "button",
|
|
@@ -25335,11 +27583,11 @@ function OhhwellsBridge() {
|
|
|
25335
27583
|
});
|
|
25336
27584
|
},
|
|
25337
27585
|
children: [
|
|
25338
|
-
/* @__PURE__ */
|
|
27586
|
+
/* @__PURE__ */ jsx36(Settings, { size: 14, "aria-hidden": true }),
|
|
25339
27587
|
"Form settings",
|
|
25340
27588
|
formPickCount ? (
|
|
25341
27589
|
// Counter pill, per the design — not a text suffix.
|
|
25342
|
-
/* @__PURE__ */
|
|
27590
|
+
/* @__PURE__ */ jsx36(
|
|
25343
27591
|
"span",
|
|
25344
27592
|
{
|
|
25345
27593
|
"data-ohw-form-count": "",
|
|
@@ -25351,8 +27599,8 @@ function OhhwellsBridge() {
|
|
|
25351
27599
|
]
|
|
25352
27600
|
}
|
|
25353
27601
|
),
|
|
25354
|
-
/* @__PURE__ */
|
|
25355
|
-
/* @__PURE__ */
|
|
27602
|
+
/* @__PURE__ */ jsx36("div", { className: "mx-0.5 h-5 w-px bg-border" }),
|
|
27603
|
+
/* @__PURE__ */ jsx36("div", { className: "flex items-center rounded-md bg-muted/70 p-0.5", children: ["default", "success"].map((state) => /* @__PURE__ */ jsx36(
|
|
25356
27604
|
"button",
|
|
25357
27605
|
{
|
|
25358
27606
|
type: "button",
|
|
@@ -25383,7 +27631,7 @@ function OhhwellsBridge() {
|
|
|
25383
27631
|
)
|
|
25384
27632
|
}
|
|
25385
27633
|
),
|
|
25386
|
-
formHoverRect && !isItemDragging && /* @__PURE__ */
|
|
27634
|
+
formHoverRect && !isItemDragging && /* @__PURE__ */ jsx36(
|
|
25387
27635
|
ItemInteractionLayer,
|
|
25388
27636
|
{
|
|
25389
27637
|
rect: formHoverRect,
|
|
@@ -25391,7 +27639,7 @@ function OhhwellsBridge() {
|
|
|
25391
27639
|
chromeGap: formHoverElRef.current && getFieldWrapper(formHoverElRef.current) ? 8 : 24
|
|
25392
27640
|
}
|
|
25393
27641
|
),
|
|
25394
|
-
fieldPickRect && fieldPickState && !isItemDragging && toolbarVariant !== "rich-text" && /* @__PURE__ */
|
|
27642
|
+
fieldPickRect && fieldPickState && !isItemDragging && toolbarVariant !== "rich-text" && /* @__PURE__ */ jsx36(
|
|
25395
27643
|
ItemInteractionLayer,
|
|
25396
27644
|
{
|
|
25397
27645
|
rect: fieldPickRect,
|
|
@@ -25403,7 +27651,7 @@ function OhhwellsBridge() {
|
|
|
25403
27651
|
dragHandleLabel: "Reorder field",
|
|
25404
27652
|
onDragHandleDragStart: handleFieldDragStart,
|
|
25405
27653
|
onDragHandleDragEnd: handleFieldDragEnd,
|
|
25406
|
-
toolbar: /* @__PURE__ */
|
|
27654
|
+
toolbar: /* @__PURE__ */ jsx36(
|
|
25407
27655
|
FormFieldToolbar,
|
|
25408
27656
|
{
|
|
25409
27657
|
type: fieldPickState.type,
|
|
@@ -25416,12 +27664,12 @@ function OhhwellsBridge() {
|
|
|
25416
27664
|
)
|
|
25417
27665
|
}
|
|
25418
27666
|
),
|
|
25419
|
-
fieldDragging ? fieldDropSlots.map((slot, i) => /* @__PURE__ */
|
|
27667
|
+
fieldDragging ? fieldDropSlots.map((slot, i) => /* @__PURE__ */ jsx36(
|
|
25420
27668
|
"div",
|
|
25421
27669
|
{
|
|
25422
27670
|
className: "pointer-events-none fixed z-[2147483644]",
|
|
25423
27671
|
style: { top: slot.top, left: slot.left, width: slot.width },
|
|
25424
|
-
children: /* @__PURE__ */
|
|
27672
|
+
children: /* @__PURE__ */ jsx36(
|
|
25425
27673
|
DropIndicator,
|
|
25426
27674
|
{
|
|
25427
27675
|
direction: "horizontal",
|
|
@@ -25434,7 +27682,7 @@ function OhhwellsBridge() {
|
|
|
25434
27682
|
)) : null,
|
|
25435
27683
|
fieldTypePickerOpen && formPickRect ? (() => {
|
|
25436
27684
|
const toolbar = document.querySelector("[data-ohw-form-toolbar]")?.getBoundingClientRect();
|
|
25437
|
-
return /* @__PURE__ */
|
|
27685
|
+
return /* @__PURE__ */ jsx36(
|
|
25438
27686
|
"div",
|
|
25439
27687
|
{
|
|
25440
27688
|
className: "pointer-events-none fixed z-[2147483645]",
|
|
@@ -25442,12 +27690,12 @@ function OhhwellsBridge() {
|
|
|
25442
27690
|
top: toolbar ? toolbar.bottom + 6 : formPickRect.top + 16,
|
|
25443
27691
|
left: toolbar ? toolbar.left : formPickRect.left + 24
|
|
25444
27692
|
},
|
|
25445
|
-
children: /* @__PURE__ */
|
|
27693
|
+
children: /* @__PURE__ */ jsx36(FieldTypePicker, { onPick: handleAddField })
|
|
25446
27694
|
}
|
|
25447
27695
|
);
|
|
25448
27696
|
})() : null,
|
|
25449
|
-
toolbarVariant === "select-frame" && toolbarRect && !linkPopover && !isItemDragging && !isFooterFrameSelection && selectedElRef.current && isNavbarLinksContainer2(selectedElRef.current) && /* @__PURE__ */
|
|
25450
|
-
toolbarVariant === "select-frame" && toolbarRect && !linkPopover && !isItemDragging && !isFooterFrameSelection && selectedElRef.current && isFooterLinksContainer(selectedElRef.current) && /* @__PURE__ */
|
|
27697
|
+
toolbarVariant === "select-frame" && toolbarRect && !linkPopover && !isItemDragging && !isFooterFrameSelection && selectedElRef.current && isNavbarLinksContainer2(selectedElRef.current) && /* @__PURE__ */ jsx36(NavbarContainerChrome, { rect: toolbarRect, onAdd: handleAddTopLevelNavItem }),
|
|
27698
|
+
toolbarVariant === "select-frame" && toolbarRect && !linkPopover && !isItemDragging && !isFooterFrameSelection && selectedElRef.current && isFooterLinksContainer(selectedElRef.current) && /* @__PURE__ */ jsx36(
|
|
25451
27699
|
FooterContainerChrome,
|
|
25452
27700
|
{
|
|
25453
27701
|
rect: toolbarRect,
|
|
@@ -25455,13 +27703,17 @@ function OhhwellsBridge() {
|
|
|
25455
27703
|
addDisabled: !canAddFooterColumn()
|
|
25456
27704
|
}
|
|
25457
27705
|
),
|
|
25458
|
-
toolbarRect && !linkPopover && (toolbarVariant === "link-action" || toolbarVariant === "select-frame" || toolbarVariant === "logo") && /* @__PURE__ */
|
|
27706
|
+
toolbarRect && !linkPopover && (toolbarVariant === "link-action" || toolbarVariant === "select-frame" || toolbarVariant === "logo") && /* @__PURE__ */ jsx36(
|
|
25459
27707
|
ItemInteractionLayer,
|
|
25460
27708
|
{
|
|
25461
|
-
rect: isItemDragging && draggedItemRect && (footerDragRef.current?.wasSelected || navDragRef.current?.wasSelected) ? draggedItemRect : toolbarRect,
|
|
27709
|
+
rect: isItemDragging && draggedItemRect && (footerDragRef.current?.wasSelected || navDragRef.current?.wasSelected || selectedElRef.current === buttonCollectionDragRef.current) ? draggedItemRect : toolbarRect,
|
|
25462
27710
|
toolbarBelowRect: selectedElRef.current && isNavigationItem2(selectedElRef.current) ? getOpenNavDropdownPanelRect(selectedElRef.current) : null,
|
|
25463
27711
|
toolbarBelowEl: selectedElRef.current && isNavigationItem2(selectedElRef.current) ? getOpenNavDropdownPanel(selectedElRef.current) : null,
|
|
25464
27712
|
elRef: glowElRef,
|
|
27713
|
+
hidden: isRectOutsideClip(
|
|
27714
|
+
isItemDragging && draggedItemRect && (footerDragRef.current?.wasSelected || navDragRef.current?.wasSelected || selectedElRef.current === buttonCollectionDragRef.current) ? draggedItemRect : toolbarRect,
|
|
27715
|
+
getIframeVisibleClip(parentScrollRef.current)
|
|
27716
|
+
),
|
|
25465
27717
|
state: isItemDragging ? "dragging" : selectedElRef.current && isNavigationItem2(selectedElRef.current) && getOpenNavDropdownPanel(selectedElRef.current) ? "active-bottom" : resolveItemInteractionState(toolbarRect, parentScrollRef.current),
|
|
25466
27718
|
showHandle: toolbarVariant === "link-action" && Boolean(reorderHrefKey) || toolbarVariant === "select-frame" && isFooterFrameSelection,
|
|
25467
27719
|
dragDisabled: reorderDragDisabled,
|
|
@@ -25471,18 +27723,25 @@ function OhhwellsBridge() {
|
|
|
25471
27723
|
onItemPointerDown: toolbarVariant === "logo" ? void 0 : handleItemChromePointerDown,
|
|
25472
27724
|
onItemClick: toolbarVariant === "logo" ? void 0 : handleItemChromeClick,
|
|
25473
27725
|
itemDragSurface: toolbarVariant !== "logo" && !isFooterFrameSelection && !selectedIsSocialsRow,
|
|
25474
|
-
toolbar: toolbarVariant === "link-action" && !isItemDragging || toolbarVariant === "select-frame" && (isFooterFrameSelection || selectedIsSocialsRow) && !isItemDragging ? /* @__PURE__ */
|
|
27726
|
+
toolbar: toolbarVariant === "link-action" && !isItemDragging || toolbarVariant === "select-frame" && (isFooterFrameSelection || selectedIsSocialsRow) && !isItemDragging ? /* @__PURE__ */ jsx36(
|
|
25475
27727
|
ItemActionToolbar,
|
|
25476
27728
|
{
|
|
25477
27729
|
onEditLink: openLinkPopoverForSelected,
|
|
25478
27730
|
onStyle: () => {
|
|
25479
27731
|
const row = selectedElRef.current;
|
|
25480
27732
|
if (!row) return;
|
|
25481
|
-
|
|
27733
|
+
suppressNextClickRef.current = true;
|
|
27734
|
+
suppressClickUntilRef.current = Date.now() + 500;
|
|
27735
|
+
if (isCtaButton(row)) {
|
|
27736
|
+
if (floatingPanelRef.current?.kind === "button-style") closeFloatingPanelOnly();
|
|
27737
|
+
else openButtonStylePanel(row);
|
|
27738
|
+
return;
|
|
27739
|
+
}
|
|
27740
|
+
if (floatingPanelRef.current?.kind === "socials-display") closeFloatingPanelOnly();
|
|
25482
27741
|
else openSocialsDisplayPanel(row);
|
|
25483
27742
|
},
|
|
25484
|
-
showStyle: selectedIsSocialsRow,
|
|
25485
|
-
styleActive: floatingPanel?.kind === "socials-display",
|
|
27743
|
+
showStyle: selectedIsSocialsRow || selectedIsCta,
|
|
27744
|
+
styleActive: floatingPanel?.kind === "socials-display" || floatingPanel?.kind === "button-style",
|
|
25486
27745
|
onAddItem: handleAddChildItem,
|
|
25487
27746
|
onSelectParent: handleSelectParent,
|
|
25488
27747
|
onDuplicate: handleDuplicateSelected,
|
|
@@ -25493,11 +27752,11 @@ function OhhwellsBridge() {
|
|
|
25493
27752
|
})(),
|
|
25494
27753
|
editLinkDisabled: false,
|
|
25495
27754
|
moreDisabled: false,
|
|
25496
|
-
deleteDisabled: selectedElRef.current !== null && (() => {
|
|
27755
|
+
deleteDisabled: selectedElRef.current !== null && isCtaButton(selectedElRef.current) && !canDeleteButton(selectedElRef.current) || selectedElRef.current !== null && (() => {
|
|
25497
27756
|
const social = getSocialItem(selectedElRef.current);
|
|
25498
27757
|
return social ? !canRemoveSocialItem(social) : false;
|
|
25499
27758
|
})(),
|
|
25500
|
-
duplicateDisabled: isFooterFrameSelection || selectedIsSocialsRow || selectedElRef.current !== null && (() => {
|
|
27759
|
+
duplicateDisabled: isFooterFrameSelection || selectedIsSocialsRow || selectedElRef.current !== null && isCtaButton(selectedElRef.current) && !canDuplicateButton(selectedElRef.current) || selectedElRef.current !== null && (() => {
|
|
25501
27760
|
const social = getSocialItem(selectedElRef.current);
|
|
25502
27761
|
const row = social ? findSocialsRow(social) : null;
|
|
25503
27762
|
return row ? !canAddSocialItem(row) : false;
|
|
@@ -25506,7 +27765,7 @@ function OhhwellsBridge() {
|
|
|
25506
27765
|
showAddItem: isFooterFrameSelection || selectedIsSocialsRow || !selectedIsCta && Boolean(
|
|
25507
27766
|
selectedElRef.current && isNavbarHrefKey(selectedElRef.current.getAttribute("data-ohw-href-key")) && !isNestedNavChild(selectedElRef.current)
|
|
25508
27767
|
),
|
|
25509
|
-
showMore:
|
|
27768
|
+
showMore: !selectedIsSocialsRow,
|
|
25510
27769
|
dropdownOpen: navDropdownPreviewOpen,
|
|
25511
27770
|
onDropdownOpenChange: handleNavDropdownOpenChange,
|
|
25512
27771
|
headingVisible: footerHeadingVisible,
|
|
@@ -25515,8 +27774,8 @@ function OhhwellsBridge() {
|
|
|
25515
27774
|
) : void 0
|
|
25516
27775
|
}
|
|
25517
27776
|
),
|
|
25518
|
-
toolbarRect && toolbarVariant === "rich-text" && !linkPopover && !isRectOutsideClip(toolbarRect, getIframeVisibleClip(parentScrollRef.current)) && /* @__PURE__ */
|
|
25519
|
-
/* @__PURE__ */
|
|
27777
|
+
toolbarRect && toolbarVariant === "rich-text" && !linkPopover && !isRectOutsideClip(toolbarRect, getIframeVisibleClip(parentScrollRef.current)) && /* @__PURE__ */ jsxs23(Fragment10, { children: [
|
|
27778
|
+
/* @__PURE__ */ jsx36(
|
|
25520
27779
|
EditGlowChrome,
|
|
25521
27780
|
{
|
|
25522
27781
|
rect: toolbarRect,
|
|
@@ -25526,7 +27785,7 @@ function OhhwellsBridge() {
|
|
|
25526
27785
|
hideHandle: isItemDragging
|
|
25527
27786
|
}
|
|
25528
27787
|
),
|
|
25529
|
-
/* @__PURE__ */
|
|
27788
|
+
/* @__PURE__ */ jsx36(
|
|
25530
27789
|
FloatingToolbar,
|
|
25531
27790
|
{
|
|
25532
27791
|
rect: toolbarRect,
|
|
@@ -25539,7 +27798,7 @@ function OhhwellsBridge() {
|
|
|
25539
27798
|
}
|
|
25540
27799
|
)
|
|
25541
27800
|
] }),
|
|
25542
|
-
maxBadge && /* @__PURE__ */
|
|
27801
|
+
maxBadge && /* @__PURE__ */ jsxs23(
|
|
25543
27802
|
"div",
|
|
25544
27803
|
{
|
|
25545
27804
|
"data-ohw-max-badge": "",
|
|
@@ -25565,7 +27824,7 @@ function OhhwellsBridge() {
|
|
|
25565
27824
|
]
|
|
25566
27825
|
}
|
|
25567
27826
|
),
|
|
25568
|
-
toggleState && !linkPopover && /* @__PURE__ */
|
|
27827
|
+
toggleState && !linkPopover && /* @__PURE__ */ jsx36(
|
|
25569
27828
|
StateToggle,
|
|
25570
27829
|
{
|
|
25571
27830
|
rect: toggleState.rect,
|
|
@@ -25574,15 +27833,15 @@ function OhhwellsBridge() {
|
|
|
25574
27833
|
onStateChange: handleStateChange
|
|
25575
27834
|
}
|
|
25576
27835
|
),
|
|
25577
|
-
sectionGap && !linkPopover && /* @__PURE__ */
|
|
27836
|
+
sectionGap && !linkPopover && /* @__PURE__ */ jsxs23(
|
|
25578
27837
|
"div",
|
|
25579
27838
|
{
|
|
25580
27839
|
"data-ohw-section-insert-line": "",
|
|
25581
27840
|
className: "fixed left-0 w-full z-2147483646 flex items-center pointer-events-none",
|
|
25582
27841
|
style: { top: sectionGap.y, transform: "translateY(-50%)" },
|
|
25583
27842
|
children: [
|
|
25584
|
-
/* @__PURE__ */
|
|
25585
|
-
/* @__PURE__ */
|
|
27843
|
+
/* @__PURE__ */ jsx36("div", { className: "flex-1 bg-bridge-primary", style: { height: 3 } }),
|
|
27844
|
+
/* @__PURE__ */ jsx36(
|
|
25586
27845
|
Badge,
|
|
25587
27846
|
{
|
|
25588
27847
|
className: "px-8 py-1 bg-bridge-primary hover:bg-bridge-primary text-primary-foreground text-xs font-medium shrink-0 rounded-full cursor-pointer pointer-events-auto",
|
|
@@ -25599,11 +27858,11 @@ function OhhwellsBridge() {
|
|
|
25599
27858
|
children: "Add Section"
|
|
25600
27859
|
}
|
|
25601
27860
|
),
|
|
25602
|
-
/* @__PURE__ */
|
|
27861
|
+
/* @__PURE__ */ jsx36("div", { className: "flex-1 bg-bridge-primary", style: { height: 3 } })
|
|
25603
27862
|
]
|
|
25604
27863
|
}
|
|
25605
27864
|
),
|
|
25606
|
-
linkPopover && dialogPortalContainer ? /* @__PURE__ */
|
|
27865
|
+
linkPopover && dialogPortalContainer ? /* @__PURE__ */ jsx36(
|
|
25607
27866
|
LinkPopover,
|
|
25608
27867
|
{
|
|
25609
27868
|
panelRef: linkPopoverPanelRef,
|
|
@@ -25620,7 +27879,7 @@ function OhhwellsBridge() {
|
|
|
25620
27879
|
},
|
|
25621
27880
|
linkPopover.key
|
|
25622
27881
|
) : null,
|
|
25623
|
-
floatingPanel && floatingPanel.kind === "socials-display" ? /* @__PURE__ */
|
|
27882
|
+
floatingPanel && floatingPanel.kind === "socials-display" ? /* @__PURE__ */ jsx36(
|
|
25624
27883
|
FloatingPanel,
|
|
25625
27884
|
{
|
|
25626
27885
|
open: true,
|
|
@@ -25630,7 +27889,7 @@ function OhhwellsBridge() {
|
|
|
25630
27889
|
onPositionChange: setFloatingPanelPos,
|
|
25631
27890
|
parentScroll: parentScrollSnap ?? parentScrollRef.current,
|
|
25632
27891
|
onClose: closeFloatingPanelOnly,
|
|
25633
|
-
children: /* @__PURE__ */
|
|
27892
|
+
children: /* @__PURE__ */ jsx36(
|
|
25634
27893
|
SocialsDisplayPanel,
|
|
25635
27894
|
{
|
|
25636
27895
|
display: socialsDisplayFor(floatingPanel.row, editContentRef.current),
|
|
@@ -25641,12 +27900,106 @@ function OhhwellsBridge() {
|
|
|
25641
27900
|
}
|
|
25642
27901
|
)
|
|
25643
27902
|
}
|
|
25644
|
-
) : null
|
|
27903
|
+
) : null,
|
|
27904
|
+
floatingPanel && floatingPanel.kind === "button-style" ? (() => {
|
|
27905
|
+
const button = document.querySelector(
|
|
27906
|
+
`[data-ohw-href-key="${CSS.escape(floatingPanel.buttonId)}"]`
|
|
27907
|
+
);
|
|
27908
|
+
if (!button) return null;
|
|
27909
|
+
captureButtonOrigin(button);
|
|
27910
|
+
const tokens = tokensFromButton(button);
|
|
27911
|
+
const current = assignmentFor(button, editContentRef.current, tokens);
|
|
27912
|
+
void buttonStyleTick;
|
|
27913
|
+
return /* @__PURE__ */ jsx36(
|
|
27914
|
+
FloatingPanel,
|
|
27915
|
+
{
|
|
27916
|
+
open: true,
|
|
27917
|
+
title: floatingPanel.title,
|
|
27918
|
+
context: floatingPanel.context,
|
|
27919
|
+
icon: /* @__PURE__ */ jsx36(Brush2, { className: "size-4 shrink-0", "aria-hidden": true }),
|
|
27920
|
+
position: floatingPanelPos,
|
|
27921
|
+
onPositionChange: setFloatingPanelPos,
|
|
27922
|
+
parentScroll: parentScrollSnap ?? parentScrollRef.current,
|
|
27923
|
+
onClose: closeFloatingPanelOnly,
|
|
27924
|
+
bodyClassName: "gap-5",
|
|
27925
|
+
children: /* @__PURE__ */ jsx36(
|
|
27926
|
+
ButtonStylePanel,
|
|
27927
|
+
{
|
|
27928
|
+
variants: tokens.variants,
|
|
27929
|
+
sizes: tokens.sizes,
|
|
27930
|
+
variant: current.variant,
|
|
27931
|
+
size: current.size,
|
|
27932
|
+
slotBackground: previewSlotBackground(button),
|
|
27933
|
+
previewLabel: (button.querySelector(
|
|
27934
|
+
'[data-ohw-editable="text"], [data-ohw-editable="plain"]'
|
|
27935
|
+
)?.textContent ?? button.textContent ?? "Book Now").trim() || "Book Now",
|
|
27936
|
+
onVariant: (variant) => applySelectedButtonStyle({ variant }),
|
|
27937
|
+
onSize: (size) => applySelectedButtonStyle({ size })
|
|
27938
|
+
},
|
|
27939
|
+
floatingPanel.key
|
|
27940
|
+
)
|
|
27941
|
+
},
|
|
27942
|
+
floatingPanel.key
|
|
27943
|
+
);
|
|
27944
|
+
})() : null
|
|
25645
27945
|
] }),
|
|
25646
27946
|
bridgeRoot
|
|
25647
27947
|
) : null
|
|
25648
27948
|
] });
|
|
25649
27949
|
}
|
|
27950
|
+
|
|
27951
|
+
// src/ui/EmptySection.tsx
|
|
27952
|
+
import Link3 from "next/link";
|
|
27953
|
+
import { Fragment as Fragment11, jsx as jsx37, jsxs as jsxs24 } from "react/jsx-runtime";
|
|
27954
|
+
function EmptySection({ title, homeHref = "/", eyebrowKey, titleKey, subtitleKey }) {
|
|
27955
|
+
return /* @__PURE__ */ jsxs24(Fragment11, { children: [
|
|
27956
|
+
/* @__PURE__ */ jsx37(
|
|
27957
|
+
"p",
|
|
27958
|
+
{
|
|
27959
|
+
style: {
|
|
27960
|
+
fontFamily: "var(--brand-font-body)",
|
|
27961
|
+
fontSize: "0.75rem",
|
|
27962
|
+
fontWeight: 500,
|
|
27963
|
+
letterSpacing: "0.15em",
|
|
27964
|
+
textTransform: "uppercase",
|
|
27965
|
+
color: "var(--brand-accent)",
|
|
27966
|
+
marginBottom: "1.5rem"
|
|
27967
|
+
},
|
|
27968
|
+
children: /* @__PURE__ */ jsx37(Link3, { href: homeHref, style: { color: "inherit" }, children: /* @__PURE__ */ jsx37("span", { ...eyebrowKey ? { "data-ohw-editable": "text", "data-ohw-key": eyebrowKey } : {}, children: "Home" }) })
|
|
27969
|
+
}
|
|
27970
|
+
),
|
|
27971
|
+
/* @__PURE__ */ jsx37(
|
|
27972
|
+
"h1",
|
|
27973
|
+
{
|
|
27974
|
+
style: {
|
|
27975
|
+
fontFamily: "var(--brand-font-heading)",
|
|
27976
|
+
fontSize: "clamp(2rem, 3.5vw, 2.75rem)",
|
|
27977
|
+
lineHeight: 1.1,
|
|
27978
|
+
letterSpacing: "-0.025em",
|
|
27979
|
+
color: "var(--brand-text)",
|
|
27980
|
+
marginBottom: "1rem"
|
|
27981
|
+
},
|
|
27982
|
+
...titleKey ? { "data-ohw-editable": "text", "data-ohw-key": titleKey, "data-ohw-max-length": 80 } : {},
|
|
27983
|
+
children: title
|
|
27984
|
+
}
|
|
27985
|
+
),
|
|
27986
|
+
/* @__PURE__ */ jsx37(
|
|
27987
|
+
"p",
|
|
27988
|
+
{
|
|
27989
|
+
style: {
|
|
27990
|
+
fontFamily: "var(--brand-font-body)",
|
|
27991
|
+
fontSize: "1rem",
|
|
27992
|
+
lineHeight: 1.7,
|
|
27993
|
+
fontWeight: 300,
|
|
27994
|
+
color: "var(--brand-text-muted)",
|
|
27995
|
+
maxWidth: "340px"
|
|
27996
|
+
},
|
|
27997
|
+
...subtitleKey ? { "data-ohw-editable": "text", "data-ohw-key": subtitleKey, "data-ohw-max-length": 160 } : {},
|
|
27998
|
+
children: "This page doesn't have any content yet."
|
|
27999
|
+
}
|
|
28000
|
+
)
|
|
28001
|
+
] });
|
|
28002
|
+
}
|
|
25650
28003
|
export {
|
|
25651
28004
|
AI_DEFAULT_BRAND,
|
|
25652
28005
|
AI_TREE_SCHEMA_VERSIONS,
|
|
@@ -25663,6 +28016,7 @@ export {
|
|
|
25663
28016
|
DropdownMenuItem,
|
|
25664
28017
|
DropdownMenuSeparator,
|
|
25665
28018
|
DropdownMenuTrigger,
|
|
28019
|
+
EmptySection,
|
|
25666
28020
|
ItemActionToolbar,
|
|
25667
28021
|
ItemInteractionLayer,
|
|
25668
28022
|
LinkEditorPanel,
|