@ohhwells/bridge 0.1.121 → 0.1.122-next.335
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.cjs
CHANGED
|
@@ -46,6 +46,7 @@ __export(index_exports, {
|
|
|
46
46
|
DropdownMenuItem: () => DropdownMenuItem,
|
|
47
47
|
DropdownMenuSeparator: () => DropdownMenuSeparator,
|
|
48
48
|
DropdownMenuTrigger: () => DropdownMenuTrigger,
|
|
49
|
+
EmptySection: () => EmptySection,
|
|
49
50
|
ItemActionToolbar: () => ItemActionToolbar,
|
|
50
51
|
ItemInteractionLayer: () => ItemInteractionLayer,
|
|
51
52
|
LinkEditorPanel: () => LinkEditorPanel,
|
|
@@ -104,6 +105,10 @@ function enforceLinkHrefs() {
|
|
|
104
105
|
|
|
105
106
|
// src/lib/ai-tree.ts
|
|
106
107
|
var AI_TREE_SCHEMA_VERSIONS = [1];
|
|
108
|
+
var BUTTON_FILL_TOKENS = ["dark", "primary", "accent", "light"];
|
|
109
|
+
var BUTTON_STYLES = ["solid", "outline", "ghost"];
|
|
110
|
+
var BUTTON_RADII = ["square", "rounded", "pill"];
|
|
111
|
+
var BUTTON_SIZES = ["s", "m", "l"];
|
|
107
112
|
var AI_DEFAULT_BRAND = {
|
|
108
113
|
palette: { dark: "#0C0A09", primary: "#0078E5", accent: "#747271", light: "#ECECEB" },
|
|
109
114
|
fonts: {
|
|
@@ -363,6 +368,118 @@ var FONT_VARS = {
|
|
|
363
368
|
var BRAND_FONT_LINK_ID = "ohw-brand-fonts";
|
|
364
369
|
var CUSTOM_FONT_STYLE_ID = "ohw-brand-custom-fonts";
|
|
365
370
|
var CUSTOM_FONT_FORMATS = /* @__PURE__ */ new Set(["woff2", "woff", "truetype", "opentype"]);
|
|
371
|
+
var BUTTON_RADIUS_PX = {
|
|
372
|
+
square: 0,
|
|
373
|
+
rounded: AI_TREE_TOKENS.radiusButton,
|
|
374
|
+
pill: 999
|
|
375
|
+
};
|
|
376
|
+
var BUTTON_SIZE_SPEC = {
|
|
377
|
+
s: {
|
|
378
|
+
paddingX: `${AI_TREE_TOKENS.spacing4}px`,
|
|
379
|
+
paddingY: `${AI_TREE_TOKENS.spacing2}px`,
|
|
380
|
+
fontSize: "14px"
|
|
381
|
+
},
|
|
382
|
+
m: {
|
|
383
|
+
paddingX: `${AI_TREE_TOKENS.spacing6}px`,
|
|
384
|
+
paddingY: `${AI_TREE_TOKENS.spacing3}px`,
|
|
385
|
+
fontSize: `${AI_TREE_TOKENS.type.button.size}px`
|
|
386
|
+
},
|
|
387
|
+
l: {
|
|
388
|
+
paddingX: `${AI_TREE_TOKENS.spacing8}px`,
|
|
389
|
+
paddingY: `${AI_TREE_TOKENS.spacing4}px`,
|
|
390
|
+
fontSize: "18px"
|
|
391
|
+
}
|
|
392
|
+
};
|
|
393
|
+
var BUTTON_SIZE_SCALE = { s: 0.85, m: 1, l: 1.25 };
|
|
394
|
+
var roundHalf = (n) => Math.round(n * 2) / 2;
|
|
395
|
+
function measureTemplateButton(variant) {
|
|
396
|
+
const root = document.documentElement;
|
|
397
|
+
const el = document.querySelector(`.btn--${variant}, .btn-${variant}`);
|
|
398
|
+
if (!el) return null;
|
|
399
|
+
const sheet = document.getElementById(BUTTON_RULES_STYLE_ID);
|
|
400
|
+
const rules = sheet?.textContent ?? "";
|
|
401
|
+
const saved = BUTTON_VAR_NAMES.map((name) => [name, root.style.getPropertyValue(name)]);
|
|
402
|
+
if (sheet) sheet.textContent = "";
|
|
403
|
+
for (const [name] of saved) root.style.removeProperty(name);
|
|
404
|
+
const cs = getComputedStyle(el);
|
|
405
|
+
const base = {
|
|
406
|
+
fontSize: parseFloat(cs.fontSize),
|
|
407
|
+
top: parseFloat(cs.paddingTop),
|
|
408
|
+
right: parseFloat(cs.paddingRight),
|
|
409
|
+
bottom: parseFloat(cs.paddingBottom),
|
|
410
|
+
left: parseFloat(cs.paddingLeft)
|
|
411
|
+
};
|
|
412
|
+
if (sheet) sheet.textContent = rules;
|
|
413
|
+
for (const [name, value] of saved) if (value) root.style.setProperty(name, value);
|
|
414
|
+
return Object.values(base).every(Number.isFinite) && base.fontSize > 0 ? base : null;
|
|
415
|
+
}
|
|
416
|
+
function scaledButtonSize(size, base) {
|
|
417
|
+
if (!base) return BUTTON_SIZE_SPEC[size];
|
|
418
|
+
const k = BUTTON_SIZE_SCALE[size];
|
|
419
|
+
const px2 = (n) => `${roundHalf(n * k)}px`;
|
|
420
|
+
return {
|
|
421
|
+
// Each side scaled on its own, so a button with uneven padding (say, room for an icon on one
|
|
422
|
+
// side) keeps its shape; the x/y vars are the averages for templates that read those instead.
|
|
423
|
+
padding: `${px2(base.top)} ${px2(base.right)} ${px2(base.bottom)} ${px2(base.left)}`,
|
|
424
|
+
paddingX: px2((base.left + base.right) / 2),
|
|
425
|
+
paddingY: px2((base.top + base.bottom) / 2),
|
|
426
|
+
fontSize: `${roundHalf(base.fontSize * k)}px`
|
|
427
|
+
};
|
|
428
|
+
}
|
|
429
|
+
var BUTTON_VAR_ROLES = ["bg", "text", "border", "radius", "padding-x", "padding-y", "padding", "font-size"];
|
|
430
|
+
var BUTTON_VAR_NAMES = ["primary", "secondary"].flatMap(
|
|
431
|
+
(variant) => BUTTON_VAR_ROLES.map((role) => `--brand-button-${variant}-${role}`)
|
|
432
|
+
);
|
|
433
|
+
var ROLES_BY_FIELD = {
|
|
434
|
+
fill: ["bg"],
|
|
435
|
+
style: ["bg", "border"],
|
|
436
|
+
textColor: ["text"],
|
|
437
|
+
radius: ["radius"],
|
|
438
|
+
size: ["padding-x", "padding-y", "padding", "font-size"]
|
|
439
|
+
};
|
|
440
|
+
function touchedButtonRoles(variant, kit) {
|
|
441
|
+
if (!kit.touched) return new Set(BUTTON_VAR_ROLES);
|
|
442
|
+
const fields = kit.touched.buttons?.[variant] ?? [];
|
|
443
|
+
const outline = fields.includes("style") && kit.buttons?.[variant]?.style === "outline";
|
|
444
|
+
return new Set(
|
|
445
|
+
fields.flatMap((f) => {
|
|
446
|
+
if (outline && (f === "fill" || f === "style")) return ["border"];
|
|
447
|
+
return ROLES_BY_FIELD[f] ?? [];
|
|
448
|
+
})
|
|
449
|
+
);
|
|
450
|
+
}
|
|
451
|
+
function buttonPalette(kit) {
|
|
452
|
+
return kit.palette ?? {
|
|
453
|
+
dark: "var(--brand-text)",
|
|
454
|
+
primary: "var(--brand-primary)",
|
|
455
|
+
accent: "var(--brand-accent)",
|
|
456
|
+
light: "var(--brand-background)"
|
|
457
|
+
};
|
|
458
|
+
}
|
|
459
|
+
function buttonVariantVars(variant, style, roles, palette) {
|
|
460
|
+
const fill = palette[style.fill];
|
|
461
|
+
const text = palette[style.textColor];
|
|
462
|
+
const size = scaledButtonSize(style.size, roles.has("font-size") ? measureTemplateButton(variant) : null);
|
|
463
|
+
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" };
|
|
464
|
+
const all = {
|
|
465
|
+
[`--brand-button-${variant}-bg`]: bg,
|
|
466
|
+
[`--brand-button-${variant}-text`]: text,
|
|
467
|
+
[`--brand-button-${variant}-border`]: border,
|
|
468
|
+
[`--brand-button-${variant}-radius`]: `${BUTTON_RADIUS_PX[style.radius]}px`,
|
|
469
|
+
[`--brand-button-${variant}-padding-x`]: size.paddingX,
|
|
470
|
+
[`--brand-button-${variant}-padding-y`]: size.paddingY,
|
|
471
|
+
...size.padding ? { [`--brand-button-${variant}-padding`]: size.padding } : {},
|
|
472
|
+
[`--brand-button-${variant}-font-size`]: size.fontSize
|
|
473
|
+
};
|
|
474
|
+
const prefix = `--brand-button-${variant}-`;
|
|
475
|
+
return Object.fromEntries(Object.entries(all).filter(([name]) => roles.has(name.slice(prefix.length))));
|
|
476
|
+
}
|
|
477
|
+
function buttonStyleVars(kit) {
|
|
478
|
+
return {
|
|
479
|
+
...buttonVariantVars("primary", kit.buttons.primary, touchedButtonRoles("primary", kit), buttonPalette(kit)),
|
|
480
|
+
...buttonVariantVars("secondary", kit.buttons.secondary, touchedButtonRoles("secondary", kit), buttonPalette(kit))
|
|
481
|
+
};
|
|
482
|
+
}
|
|
366
483
|
function brandColorVars(palette) {
|
|
367
484
|
const { dark, primary, accent, light } = palette;
|
|
368
485
|
const mix = (a, aPct, b) => `color-mix(in srgb, ${a} ${aPct}%, ${b})`;
|
|
@@ -390,6 +507,11 @@ function brandColorVars(palette) {
|
|
|
390
507
|
"--brand-on-primary": light
|
|
391
508
|
};
|
|
392
509
|
}
|
|
510
|
+
function isButtonStyle(value) {
|
|
511
|
+
if (!value || typeof value !== "object") return false;
|
|
512
|
+
const v = value;
|
|
513
|
+
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);
|
|
514
|
+
}
|
|
393
515
|
function parseCustomFontWeight(raw) {
|
|
394
516
|
if (typeof raw !== "object" || raw === null) return null;
|
|
395
517
|
const w = raw;
|
|
@@ -409,6 +531,15 @@ function parseCustomFont(raw) {
|
|
|
409
531
|
if (weights.length === 0) return null;
|
|
410
532
|
return { family: f.family, label: f.label, weights };
|
|
411
533
|
}
|
|
534
|
+
var BUTTON_FIELDS = Object.keys(ROLES_BY_FIELD);
|
|
535
|
+
function parseTouchedButtons(raw) {
|
|
536
|
+
const out = {};
|
|
537
|
+
for (const variant of ["primary", "secondary"]) {
|
|
538
|
+
const list = raw?.[variant];
|
|
539
|
+
if (Array.isArray(list)) out[variant] = BUTTON_FIELDS.filter((f) => list.includes(f));
|
|
540
|
+
}
|
|
541
|
+
return out;
|
|
542
|
+
}
|
|
412
543
|
function parseBrandKit(raw) {
|
|
413
544
|
if (!raw) return null;
|
|
414
545
|
try {
|
|
@@ -418,11 +549,21 @@ function parseBrandKit(raw) {
|
|
|
418
549
|
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;
|
|
419
550
|
const fonts = f && typeof f.heading === "string" && typeof f.body === "string" ? { heading: f.heading, body: f.body } : void 0;
|
|
420
551
|
const customFonts = Array.isArray(parsed?.customFonts) ? parsed.customFonts.map(parseCustomFont).filter((c) => c !== null) : void 0;
|
|
421
|
-
|
|
552
|
+
const b = parsed?.buttons;
|
|
553
|
+
const buttons = b && isButtonStyle(b.primary) && isButtonStyle(b.secondary) ? { primary: b.primary, secondary: b.secondary } : void 0;
|
|
554
|
+
if (!palette && !fonts && !customFonts && !buttons) return null;
|
|
422
555
|
return {
|
|
423
556
|
...palette ? { palette } : {},
|
|
424
557
|
...fonts ? { fonts } : {},
|
|
425
|
-
...customFonts ? { customFonts } : {}
|
|
558
|
+
...customFonts ? { customFonts } : {},
|
|
559
|
+
...buttons ? { buttons } : {},
|
|
560
|
+
...parsed.touched && typeof parsed.touched === "object" ? {
|
|
561
|
+
touched: {
|
|
562
|
+
palette: parsed.touched.palette === true,
|
|
563
|
+
fonts: parsed.touched.fonts === true,
|
|
564
|
+
buttons: parseTouchedButtons(parsed.touched.buttons)
|
|
565
|
+
}
|
|
566
|
+
} : {}
|
|
426
567
|
};
|
|
427
568
|
} catch {
|
|
428
569
|
return null;
|
|
@@ -451,6 +592,39 @@ function loadBrandFonts(families) {
|
|
|
451
592
|
}
|
|
452
593
|
if (link.href !== href) link.href = href;
|
|
453
594
|
}
|
|
595
|
+
var BUTTON_RULES_STYLE_ID = "ohw-brand-button-rules";
|
|
596
|
+
function buttonRulesCss(kit) {
|
|
597
|
+
const rule = (variant) => {
|
|
598
|
+
const roles = touchedButtonRoles(variant, kit);
|
|
599
|
+
const v = (role) => `var(--brand-button-${variant}-${role})`;
|
|
600
|
+
const decls = [];
|
|
601
|
+
if (roles.has("bg")) decls.push(`background:${v("bg")} !important`);
|
|
602
|
+
if (roles.has("text")) decls.push(`color:${v("text")} !important`);
|
|
603
|
+
if (roles.has("border")) decls.push(`border:1.5px solid ${v("border")} !important`);
|
|
604
|
+
if (roles.has("radius")) decls.push(`border-radius:${v("radius")} !important`);
|
|
605
|
+
if (roles.has("padding-x")) decls.push(`padding:var(--brand-button-${variant}-padding, ${v("padding-y")} ${v("padding-x")}) !important`);
|
|
606
|
+
if (roles.has("font-size")) decls.push(`font-size:${v("font-size")} !important`);
|
|
607
|
+
if (decls.length === 0) return "";
|
|
608
|
+
const selectors = [`html .btn--${variant}`, `html .btn-${variant}`];
|
|
609
|
+
const labelRule = roles.has("text") ? `${selectors.map((x) => `${x} *`).join(",")}{color:inherit !important}` : "";
|
|
610
|
+
return `${selectors.join(",")}{${decls.join(";")}}` + labelRule + (roles.has("bg") ? `${selectors.map((x) => `${x}:hover`).join(",")}{opacity:0.88}` : "");
|
|
611
|
+
};
|
|
612
|
+
return rule("primary") + rule("secondary");
|
|
613
|
+
}
|
|
614
|
+
function syncButtonRules(kit) {
|
|
615
|
+
let el = document.getElementById(BUTTON_RULES_STYLE_ID);
|
|
616
|
+
const css = kit ? buttonRulesCss(kit) : "";
|
|
617
|
+
if (!css) {
|
|
618
|
+
el?.remove();
|
|
619
|
+
return;
|
|
620
|
+
}
|
|
621
|
+
if (!el) {
|
|
622
|
+
el = document.createElement("style");
|
|
623
|
+
el.id = BUTTON_RULES_STYLE_ID;
|
|
624
|
+
document.head.appendChild(el);
|
|
625
|
+
}
|
|
626
|
+
if (el.textContent !== css) el.textContent = css;
|
|
627
|
+
}
|
|
454
628
|
function escapeCssString(value) {
|
|
455
629
|
return value.replace(/\\/g, "\\\\").replace(/'/g, "\\'");
|
|
456
630
|
}
|
|
@@ -476,28 +650,47 @@ function loadCustomFonts(fonts) {
|
|
|
476
650
|
function applyBrandToDom(kit) {
|
|
477
651
|
const root = document.documentElement;
|
|
478
652
|
if (!kit) {
|
|
479
|
-
for (const name of [...BRAND_VAR_NAMES, ...LEGACY_BRAND_VAR_NAMES])
|
|
653
|
+
for (const name of [...BRAND_VAR_NAMES, ...LEGACY_BRAND_VAR_NAMES, ...BUTTON_VAR_NAMES]) {
|
|
654
|
+
root.style.removeProperty(name);
|
|
655
|
+
}
|
|
480
656
|
for (const name of [...FONT_VARS.heading, ...FONT_VARS.body]) root.style.removeProperty(name);
|
|
481
657
|
document.getElementById(BRAND_FONT_LINK_ID)?.remove();
|
|
482
658
|
document.getElementById(CUSTOM_FONT_STYLE_ID)?.remove();
|
|
659
|
+
syncButtonRules(null);
|
|
483
660
|
return;
|
|
484
661
|
}
|
|
662
|
+
const applyPalette = kit.touched ? kit.touched.palette === true : true;
|
|
663
|
+
const applyFonts = kit.touched ? kit.touched.fonts === true : true;
|
|
485
664
|
if (kit.palette) {
|
|
486
|
-
|
|
665
|
+
if (applyPalette) {
|
|
666
|
+
for (const [name, value] of Object.entries(brandColorVars(kit.palette))) root.style.setProperty(name, value);
|
|
667
|
+
} else {
|
|
668
|
+
for (const name of [...BRAND_VAR_NAMES, ...LEGACY_BRAND_VAR_NAMES]) root.style.removeProperty(name);
|
|
669
|
+
}
|
|
487
670
|
}
|
|
671
|
+
if (kit.buttons) {
|
|
672
|
+
for (const name of BUTTON_VAR_NAMES) root.style.removeProperty(name);
|
|
673
|
+
for (const [name, value] of Object.entries(buttonStyleVars({ ...kit, buttons: kit.buttons }))) root.style.setProperty(name, value);
|
|
674
|
+
}
|
|
675
|
+
syncButtonRules(kit.buttons ? kit : null);
|
|
488
676
|
if (kit.customFonts) {
|
|
489
677
|
loadCustomFonts(kit.customFonts);
|
|
490
678
|
}
|
|
491
679
|
if (kit.fonts) {
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
(
|
|
499
|
-
|
|
500
|
-
|
|
680
|
+
if (applyFonts) {
|
|
681
|
+
const heading = quoteFamily(kit.fonts.heading);
|
|
682
|
+
const body = quoteFamily(kit.fonts.body);
|
|
683
|
+
for (const name of FONT_VARS.heading) root.style.setProperty(name, heading);
|
|
684
|
+
for (const name of FONT_VARS.body) root.style.setProperty(name, body);
|
|
685
|
+
const customFamilies = new Set((kit.customFonts ?? []).map((f) => f.family));
|
|
686
|
+
const googleFamilies = [familyOf(kit.fonts.heading), familyOf(kit.fonts.body)].filter(
|
|
687
|
+
(f) => !customFamilies.has(f)
|
|
688
|
+
);
|
|
689
|
+
loadBrandFonts(googleFamilies);
|
|
690
|
+
} else {
|
|
691
|
+
for (const name of [...FONT_VARS.heading, ...FONT_VARS.body]) root.style.removeProperty(name);
|
|
692
|
+
document.getElementById(BRAND_FONT_LINK_ID)?.remove();
|
|
693
|
+
}
|
|
501
694
|
}
|
|
502
695
|
}
|
|
503
696
|
|
|
@@ -598,9 +791,9 @@ function styleSheetCss() {
|
|
|
598
791
|
);
|
|
599
792
|
}
|
|
600
793
|
const pad = { tight: 40, balanced: 64, airy: 96 };
|
|
601
|
-
for (const [spacing,
|
|
794
|
+
for (const [spacing, px2] of Object.entries(pad)) {
|
|
602
795
|
rules.push(
|
|
603
|
-
`[data-ohw-style-spacing="${spacing}"] { padding-top: ${
|
|
796
|
+
`[data-ohw-style-spacing="${spacing}"] { padding-top: ${px2}px !important; padding-bottom: ${px2}px !important; }`
|
|
604
797
|
);
|
|
605
798
|
}
|
|
606
799
|
rules.push(
|
|
@@ -647,7 +840,6 @@ var NODE_PROPS = [
|
|
|
647
840
|
"color",
|
|
648
841
|
"font-family",
|
|
649
842
|
"font-size",
|
|
650
|
-
"background",
|
|
651
843
|
"text-align",
|
|
652
844
|
"justify-content",
|
|
653
845
|
"align-items"
|
|
@@ -697,9 +889,6 @@ function clearNodeProps(root) {
|
|
|
697
889
|
h.removeAttribute(NODE_WROTE_ATTR);
|
|
698
890
|
}
|
|
699
891
|
}
|
|
700
|
-
function buttonSurfaceOf(el) {
|
|
701
|
-
return el.closest("a, button") ?? el;
|
|
702
|
-
}
|
|
703
892
|
function alignSubjectOf(el) {
|
|
704
893
|
const button = el.closest('[data-ohw-role="button"]');
|
|
705
894
|
if (button?.parentElement) return button.parentElement;
|
|
@@ -817,18 +1006,6 @@ function applyStylesToDom(store) {
|
|
|
817
1006
|
);
|
|
818
1007
|
subject.setAttribute(NODE_WROTE_ATTR, "");
|
|
819
1008
|
}
|
|
820
|
-
if (override.buttonBackground !== void 0 || override.buttonText !== void 0) {
|
|
821
|
-
const surface = buttonSurfaceOf(el);
|
|
822
|
-
if (override.buttonBackground !== void 0) {
|
|
823
|
-
saveInline(surface, "background");
|
|
824
|
-
surface.style.setProperty("background", override.buttonBackground, "important");
|
|
825
|
-
}
|
|
826
|
-
if (override.buttonText !== void 0) {
|
|
827
|
-
saveInline(surface, "color");
|
|
828
|
-
surface.style.setProperty("color", override.buttonText, "important");
|
|
829
|
-
}
|
|
830
|
-
surface.setAttribute(NODE_WROTE_ATTR, "");
|
|
831
|
-
}
|
|
832
1009
|
}
|
|
833
1010
|
}
|
|
834
1011
|
for (const [sectionId, override] of Object.entries(store.sections)) {
|
|
@@ -1414,7 +1591,59 @@ var AI_MOBILE_CSS = [
|
|
|
1414
1591
|
"[data-ai-grid]{grid-template-columns:repeat(2, 1fr) !important}",
|
|
1415
1592
|
"}"
|
|
1416
1593
|
].join("");
|
|
1417
|
-
function
|
|
1594
|
+
function buttonSizeSpec(size) {
|
|
1595
|
+
switch (size) {
|
|
1596
|
+
case "s":
|
|
1597
|
+
return { padding: `${AI_TREE_TOKENS.spacing2}px ${AI_TREE_TOKENS.spacing4}px`, fontSize: 14 };
|
|
1598
|
+
case "l":
|
|
1599
|
+
return { padding: `${AI_TREE_TOKENS.spacing4}px ${AI_TREE_TOKENS.spacing8}px`, fontSize: 18 };
|
|
1600
|
+
case "m":
|
|
1601
|
+
default:
|
|
1602
|
+
return { padding: `${AI_TREE_TOKENS.spacing3}px ${AI_TREE_TOKENS.spacing6}px`, fontSize: AI_TREE_TOKENS.type.button.size };
|
|
1603
|
+
}
|
|
1604
|
+
}
|
|
1605
|
+
function buttonRadiusPx(radius) {
|
|
1606
|
+
switch (radius) {
|
|
1607
|
+
case "square":
|
|
1608
|
+
return 0;
|
|
1609
|
+
case "pill":
|
|
1610
|
+
return 999;
|
|
1611
|
+
case "rounded":
|
|
1612
|
+
default:
|
|
1613
|
+
return AI_TREE_TOKENS.radiusButton;
|
|
1614
|
+
}
|
|
1615
|
+
}
|
|
1616
|
+
function resolveButtonToken(brand, token) {
|
|
1617
|
+
return brand.palette[token];
|
|
1618
|
+
}
|
|
1619
|
+
function buttonColorStyle(ctx, variant) {
|
|
1620
|
+
const token = ctx.brand.buttons?.[variant];
|
|
1621
|
+
if (!token) return null;
|
|
1622
|
+
const fill = resolveButtonToken(ctx.brand, token.fill);
|
|
1623
|
+
const text = resolveButtonToken(ctx.brand, token.textColor);
|
|
1624
|
+
switch (token.style) {
|
|
1625
|
+
case "outline":
|
|
1626
|
+
return { background: "transparent", border: `1px solid ${fill}`, color: text };
|
|
1627
|
+
case "ghost":
|
|
1628
|
+
return { background: "transparent", border: "1px solid transparent", color: text };
|
|
1629
|
+
case "solid":
|
|
1630
|
+
default:
|
|
1631
|
+
return { background: fill, color: text };
|
|
1632
|
+
}
|
|
1633
|
+
}
|
|
1634
|
+
function buttonShellStyle(ctx, variant, fullWidth) {
|
|
1635
|
+
const buttonToken = ctx.brand.buttons?.[variant];
|
|
1636
|
+
if (buttonToken) {
|
|
1637
|
+
const { padding, fontSize } = buttonSizeSpec(buttonToken.size);
|
|
1638
|
+
return {
|
|
1639
|
+
borderRadius: buttonRadiusPx(buttonToken.radius),
|
|
1640
|
+
padding,
|
|
1641
|
+
fontFamily: ctx.brand.fonts.body,
|
|
1642
|
+
fontSize,
|
|
1643
|
+
lineHeight: AI_TREE_TOKENS.type.button.line,
|
|
1644
|
+
fontWeight: AI_TREE_TOKENS.type.button.weight
|
|
1645
|
+
};
|
|
1646
|
+
}
|
|
1418
1647
|
const bs = ctx.buttonStyle;
|
|
1419
1648
|
if (bs) {
|
|
1420
1649
|
return {
|
|
@@ -1524,6 +1753,22 @@ function pricingCardEmphasis(featured, ctx, hasBg) {
|
|
|
1524
1753
|
function textAttrs(ctx, path) {
|
|
1525
1754
|
return ctx.keyFor ? { "data-ohw-key": ctx.keyFor(path), "data-ohw-editable": "text" } : {};
|
|
1526
1755
|
}
|
|
1756
|
+
var AI_RESPONSIVE_CSS = [
|
|
1757
|
+
"@media (max-width: 960px) {",
|
|
1758
|
+
" [data-ai-responsive] [data-ai-grid] { grid-template-columns: repeat(2, 1fr) !important; }",
|
|
1759
|
+
' [data-ai-responsive] [data-ai-grid="1"] { grid-template-columns: 1fr !important; }',
|
|
1760
|
+
"}",
|
|
1761
|
+
"@media (max-width: 640px) {",
|
|
1762
|
+
" [data-ai-responsive] [data-ai-grid] { grid-template-columns: 1fr !important; }",
|
|
1763
|
+
" [data-ai-responsive] [data-ai-columns] > * { grid-column: 1 / -1 !important; }",
|
|
1764
|
+
// Group containers flatten to a column on phones; span placements come along for free.
|
|
1765
|
+
" [data-ai-responsive] [data-ai-group] { display: flex !important; flex-direction: column !important; }",
|
|
1766
|
+
" [data-ai-responsive] [data-ai-group] > * { grid-column: auto !important; }",
|
|
1767
|
+
" [data-ai-responsive] [data-ai-section-inner] { padding-left: 20px !important; padding-right: 20px !important; }",
|
|
1768
|
+
" [data-ai-responsive] { overflow-x: hidden; }",
|
|
1769
|
+
" [data-ai-responsive] img { max-width: 100%; }",
|
|
1770
|
+
"}"
|
|
1771
|
+
].join("\n");
|
|
1527
1772
|
var TRANSPARENT_PX = "data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7";
|
|
1528
1773
|
function MediaBox({
|
|
1529
1774
|
refValue,
|
|
@@ -1541,9 +1786,9 @@ function MediaBox({
|
|
|
1541
1786
|
const url = refValue ? ctx.resolveMedia(refValue) : null;
|
|
1542
1787
|
const isIcon = /^(lucide|simple):/.test(refValue);
|
|
1543
1788
|
const aspectRatio = aspect && /^\d+:\d+$/.test(aspect) ? aspect.replace(":", " / ") : void 0;
|
|
1544
|
-
const editAttrs = ctx.keyFor && editPath
|
|
1789
|
+
const editAttrs = ctx.keyFor && editPath ? {
|
|
1545
1790
|
"data-ohw-key": ctx.keyFor(editPath),
|
|
1546
|
-
...genericImageEdit ? { "data-ohw-editable": "image" } : {}
|
|
1791
|
+
...isIcon ? { "data-ohw-editable": "icon" } : genericImageEdit ? { "data-ohw-editable": "image" } : {}
|
|
1547
1792
|
} : {};
|
|
1548
1793
|
if (isIcon) {
|
|
1549
1794
|
const Icon = refValue.startsWith("lucide:") ? lucideByName(refValue.slice(7)) : null;
|
|
@@ -1551,6 +1796,7 @@ function MediaBox({
|
|
|
1551
1796
|
"span",
|
|
1552
1797
|
{
|
|
1553
1798
|
"data-ai-icon": refValue,
|
|
1799
|
+
...editAttrs,
|
|
1554
1800
|
style: {
|
|
1555
1801
|
display: "inline-flex",
|
|
1556
1802
|
width: 48,
|
|
@@ -1610,12 +1856,16 @@ function ButtonEl({
|
|
|
1610
1856
|
secondaryColor
|
|
1611
1857
|
}) {
|
|
1612
1858
|
const secondary = slots.variant === "secondary";
|
|
1859
|
+
const variant = secondary ? "secondary" : "primary";
|
|
1860
|
+
const tokenColorStyle = buttonColorStyle(ctx, variant);
|
|
1613
1861
|
const href = str(slots.href);
|
|
1614
1862
|
const linkAttrs = ctx.keyFor && path ? { "data-ohw-href-key": ctx.keyFor(`${path}.href`), "data-ohw-role": "button" } : {};
|
|
1615
1863
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1616
1864
|
"a",
|
|
1617
1865
|
{
|
|
1618
1866
|
href: href || void 0,
|
|
1867
|
+
className: `btn btn--${variant}`,
|
|
1868
|
+
"data-ohw-btn-variant": variant,
|
|
1619
1869
|
...linkAttrs,
|
|
1620
1870
|
style: {
|
|
1621
1871
|
display: fullWidth ? "flex" : "inline-flex",
|
|
@@ -1625,13 +1875,13 @@ function ButtonEl({
|
|
|
1625
1875
|
textDecoration: "none",
|
|
1626
1876
|
cursor: "pointer",
|
|
1627
1877
|
whiteSpace: "nowrap",
|
|
1628
|
-
...buttonShellStyle(ctx, fullWidth),
|
|
1629
|
-
...secondary ? { border: `1px solid ${secondaryColor ?? ctx.brand.palette.dark}`, color: secondaryColor ?? ctx.brand.palette.dark } : (
|
|
1878
|
+
...buttonShellStyle(ctx, variant, fullWidth),
|
|
1879
|
+
...tokenColorStyle ?? (secondary ? { border: `1px solid ${secondaryColor ?? ctx.brand.palette.dark}`, color: secondaryColor ?? ctx.brand.palette.dark } : (
|
|
1630
1880
|
// Off-band, prefer the template button's measured fill/label pair — a template may
|
|
1631
1881
|
// fill its CTAs with any token (hvac: accent bg, primary text). On an accent band
|
|
1632
1882
|
// the flipped palette keeps contrast, so the brand-driven colours stay.
|
|
1633
1883
|
!ctx.buttonLabel && ctx.buttonStyle?.background ? { background: ctx.buttonStyle.background, color: ctx.buttonStyle.color } : { background: ctx.brand.palette.primary, color: ctx.buttonLabel ?? primaryButtonLabel(ctx.brand) }
|
|
1634
|
-
)
|
|
1884
|
+
))
|
|
1635
1885
|
},
|
|
1636
1886
|
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { ...path ? textAttrs(ctx, `${path}.label`) : {}, children: str(slots.label) })
|
|
1637
1887
|
}
|
|
@@ -2605,7 +2855,7 @@ function CollectionBlock({ node, ctx, path }) {
|
|
|
2605
2855
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
2606
2856
|
"div",
|
|
2607
2857
|
{
|
|
2608
|
-
"data-ai-grid":
|
|
2858
|
+
"data-ai-grid": String(itemsPerRow),
|
|
2609
2859
|
"data-ohw-pricing-collection": isPricing ? "" : void 0,
|
|
2610
2860
|
style: {
|
|
2611
2861
|
display: "grid",
|
|
@@ -2853,18 +3103,21 @@ function renderNode(node, ctx, path) {
|
|
|
2853
3103
|
"button",
|
|
2854
3104
|
{
|
|
2855
3105
|
type: "submit",
|
|
3106
|
+
className: "btn btn--primary",
|
|
3107
|
+
"data-ohw-btn-variant": "primary",
|
|
3108
|
+
"data-ohw-role": "button",
|
|
2856
3109
|
style: {
|
|
2857
3110
|
alignSelf: submitAlign,
|
|
2858
3111
|
border: "none",
|
|
2859
3112
|
cursor: "pointer",
|
|
2860
3113
|
// Shape/padding/typography follow the host template's own buttons.
|
|
2861
|
-
...buttonShellStyle(ctx),
|
|
3114
|
+
...buttonShellStyle(ctx, "primary"),
|
|
2862
3115
|
// Brand-styled: the template button's measured fill/label pair off-band, else
|
|
2863
3116
|
// primary fill with a brand-derived label so it reads on custom palettes.
|
|
2864
|
-
|
|
3117
|
+
...buttonColorStyle(ctx, "primary") ?? (!ctx.buttonLabel && ctx.buttonStyle?.background ? { background: ctx.buttonStyle.background, color: ctx.buttonStyle.color } : {
|
|
2865
3118
|
background: ctx.brand.palette.primary,
|
|
2866
3119
|
color: ctx.buttonLabel ?? primaryButtonLabel(ctx.brand)
|
|
2867
|
-
}
|
|
3120
|
+
})
|
|
2868
3121
|
},
|
|
2869
3122
|
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { ...textAttrs(ctx, `${path}.c${i}.label`), children: str(cs.label) })
|
|
2870
3123
|
},
|
|
@@ -2961,6 +3214,7 @@ function AiTreeRenderer({
|
|
|
2961
3214
|
{
|
|
2962
3215
|
"data-ai-section": tree.tag ?? "",
|
|
2963
3216
|
...bgAttrs,
|
|
3217
|
+
"data-ai-responsive": "",
|
|
2964
3218
|
style: {
|
|
2965
3219
|
position: "relative",
|
|
2966
3220
|
padding: `${pad}px 0`,
|
|
@@ -2971,12 +3225,13 @@ function AiTreeRenderer({
|
|
|
2971
3225
|
color: settings.sectionBackground === "accent" ? blockBrand.palette.dark : void 0
|
|
2972
3226
|
},
|
|
2973
3227
|
children: [
|
|
2974
|
-
|
|
3228
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("style", { children: AI_RESPONSIVE_CSS }),
|
|
2975
3229
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("style", { children: AI_MOBILE_CSS }),
|
|
3230
|
+
isOverlay && backgroundUrl && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: { position: "absolute", inset: 0, background: `rgba(255,255,255,${overlayAlpha})` } }),
|
|
2976
3231
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
2977
3232
|
"div",
|
|
2978
3233
|
{
|
|
2979
|
-
"data-ai-
|
|
3234
|
+
"data-ai-section-inner": "",
|
|
2980
3235
|
style: {
|
|
2981
3236
|
position: "relative",
|
|
2982
3237
|
maxWidth: AI_TREE_TOKENS.sectionMaxWidth,
|
|
@@ -2987,7 +3242,7 @@ function AiTreeRenderer({
|
|
|
2987
3242
|
children: tree.rows.map((row, r2) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
2988
3243
|
"div",
|
|
2989
3244
|
{
|
|
2990
|
-
"data-ai-
|
|
3245
|
+
"data-ai-columns": "",
|
|
2991
3246
|
style: {
|
|
2992
3247
|
display: "grid",
|
|
2993
3248
|
gridTemplateColumns: "repeat(12, 1fr)",
|
|
@@ -3167,12 +3422,12 @@ function deriveTemplateButtonStyle() {
|
|
|
3167
3422
|
cs.borderBottomLeftRadius
|
|
3168
3423
|
].map((v) => v || "0px");
|
|
3169
3424
|
const radius = corners.every((v) => v === corners[0]) ? corners[0] : corners.join(" ");
|
|
3170
|
-
const
|
|
3171
|
-
const lineHeight =
|
|
3172
|
-
const contentH = btn.getBoundingClientRect().height -
|
|
3425
|
+
const px2 = (v) => parseFloat(v) || 0;
|
|
3426
|
+
const lineHeight = px2(cs.lineHeight) || px2(cs.fontSize) * 1.2;
|
|
3427
|
+
const contentH = btn.getBoundingClientRect().height - px2(cs.borderTopWidth) - px2(cs.borderBottomWidth);
|
|
3173
3428
|
const impliedY = Math.round(Math.max(0, (contentH - lineHeight) / 2));
|
|
3174
|
-
const padY = Math.max(
|
|
3175
|
-
const padX = Math.max(
|
|
3429
|
+
const padY = Math.max(px2(cs.paddingTop), px2(cs.paddingBottom), impliedY);
|
|
3430
|
+
const padX = Math.max(px2(cs.paddingLeft), px2(cs.paddingRight));
|
|
3176
3431
|
return {
|
|
3177
3432
|
radius: radius || "10px",
|
|
3178
3433
|
padding: `${padY}px ${padX}px`,
|
|
@@ -3391,9 +3646,10 @@ function applyAiSectionsToDom(state, options) {
|
|
|
3391
3646
|
if (existing && existing.serialized === serialized && existing.container.isConnected) {
|
|
3392
3647
|
continue;
|
|
3393
3648
|
}
|
|
3394
|
-
const isNewMount = !existing || !existing.container.isConnected;
|
|
3395
3649
|
let container = existing?.container;
|
|
3650
|
+
let isNewMount = false;
|
|
3396
3651
|
if (!container || !container.isConnected) {
|
|
3652
|
+
isNewMount = true;
|
|
3397
3653
|
existing?.root.unmount();
|
|
3398
3654
|
container?.remove();
|
|
3399
3655
|
container = document.createElement("div");
|
|
@@ -8089,6 +8345,14 @@ function ItemActionToolbar({
|
|
|
8089
8345
|
e.preventDefault();
|
|
8090
8346
|
e.stopPropagation();
|
|
8091
8347
|
onStyle?.();
|
|
8348
|
+
},
|
|
8349
|
+
// Same as Edit link: mousedown opens the panel and remounts this toolbar
|
|
8350
|
+
// (styleActive flips). Without stopping click, the gesture lands on whatever
|
|
8351
|
+
// is now under the cursor — navbar CTAs park the toolbar below the button, so
|
|
8352
|
+
// that miss deselects and the panel closes as soon as it opens.
|
|
8353
|
+
onClick: (e) => {
|
|
8354
|
+
e.preventDefault();
|
|
8355
|
+
e.stopPropagation();
|
|
8092
8356
|
}
|
|
8093
8357
|
},
|
|
8094
8358
|
children: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(import_lucide_react3.Brush, { className: "size-4 shrink-0", "aria-hidden": true })
|
|
@@ -8411,20 +8675,32 @@ function ItemInteractionLayer({
|
|
|
8411
8675
|
itemDragSurface = true,
|
|
8412
8676
|
chromeGap,
|
|
8413
8677
|
toolbarAlign = "center",
|
|
8678
|
+
hidden = false,
|
|
8414
8679
|
className
|
|
8415
8680
|
}) {
|
|
8681
|
+
const localRef = (0, import_react7.useRef)(null);
|
|
8682
|
+
(0, import_react7.useLayoutEffect)(() => {
|
|
8683
|
+
const node = localRef.current;
|
|
8684
|
+
if (!node) return;
|
|
8685
|
+
node.style.display = hidden ? "none" : "block";
|
|
8686
|
+
}, [hidden, rect.top, rect.left, rect.width, rect.height, state]);
|
|
8416
8687
|
if (state === "default") return null;
|
|
8417
8688
|
const gap = chromeGap ?? (state === "hover" ? HOVER_CHROME_GAP : SELECTION_CHROME_GAP);
|
|
8418
8689
|
const isActive = state === "active-top" || state === "active-bottom";
|
|
8419
8690
|
const isDragging = state === "dragging";
|
|
8420
8691
|
const showToolbar = isActive && toolbar;
|
|
8421
8692
|
const showDragHandle = (isActive || isDragging) && showHandle;
|
|
8422
|
-
const itemDragEnabled = itemDragSurface && isActive &&
|
|
8693
|
+
const itemDragEnabled = itemDragSurface && isActive && !isDragging && !dragDisabled && Boolean(showHandle || onItemPointerDown);
|
|
8423
8694
|
const useDetachedBelowToolbar = Boolean(showToolbar && state === "active-bottom" && toolbarBelowRect);
|
|
8695
|
+
const setRootRef = (node) => {
|
|
8696
|
+
localRef.current = node;
|
|
8697
|
+
if (typeof elRef === "function") elRef(node);
|
|
8698
|
+
else if (elRef) elRef.current = node;
|
|
8699
|
+
};
|
|
8424
8700
|
return /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(
|
|
8425
8701
|
"div",
|
|
8426
8702
|
{
|
|
8427
|
-
ref:
|
|
8703
|
+
ref: setRootRef,
|
|
8428
8704
|
"data-ohw-item-interaction": "",
|
|
8429
8705
|
"data-ohw-item-interaction-state": state,
|
|
8430
8706
|
className: cn("pointer-events-none", className),
|
|
@@ -8434,7 +8710,8 @@ function ItemInteractionLayer({
|
|
|
8434
8710
|
left: rect.left - gap,
|
|
8435
8711
|
width: rect.width + gap * 2,
|
|
8436
8712
|
height: rect.height + gap * 2,
|
|
8437
|
-
zIndex: getChromeZIndex(state)
|
|
8713
|
+
zIndex: getChromeZIndex(state),
|
|
8714
|
+
display: hidden ? "none" : "block"
|
|
8438
8715
|
},
|
|
8439
8716
|
children: [
|
|
8440
8717
|
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
@@ -9266,6 +9543,7 @@ function MediaOverlay({
|
|
|
9266
9543
|
(prev) => prev && prev.fullWidth === width && prev.height === height ? prev : { fullWidth: width, height }
|
|
9267
9544
|
);
|
|
9268
9545
|
}, [isVideo]);
|
|
9546
|
+
const replaceLabel = isVideo ? "Replace video" : hover.elementType === "bg-image" ? "Replace background" : "Replace image";
|
|
9269
9547
|
const replaceMode = buttonSize ? replaceButtonMode({ width: rect.width, height: rect.height }, buttonSize) : "none";
|
|
9270
9548
|
const box = {
|
|
9271
9549
|
position: "fixed",
|
|
@@ -9364,11 +9642,10 @@ function MediaOverlay({
|
|
|
9364
9642
|
className: "flex items-center justify-center cursor-pointer",
|
|
9365
9643
|
style: {
|
|
9366
9644
|
...box,
|
|
9367
|
-
//
|
|
9368
|
-
//
|
|
9369
|
-
//
|
|
9370
|
-
|
|
9371
|
-
pointerEvents: hover.hasTextOverlap || cueOnly ? "none" : "auto",
|
|
9645
|
+
// Visual only. `pointer-events: auto` on this full-bleed rect covered the navbar
|
|
9646
|
+
// (hero bg includes the absolute TopNav) and swallowed CTA press-drag. Text overlay
|
|
9647
|
+
// and cueOnly also need clicks to fall through — Replace / video controls opt back in.
|
|
9648
|
+
pointerEvents: "none",
|
|
9372
9649
|
// Selected: a firm component ring with no wash, so the image reads as chosen rather
|
|
9373
9650
|
// than hovered. Hover keeps the existing tinted preview.
|
|
9374
9651
|
boxShadow: selected ? "inset 0 0 0 2px var(--color-bridge-primary)" : "inset 0 0 0 1.5px var(--color-bridge-primary)",
|
|
@@ -9395,17 +9672,17 @@ function MediaOverlay({
|
|
|
9395
9672
|
},
|
|
9396
9673
|
children: [
|
|
9397
9674
|
isVideo ? /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(import_lucide_react5.Film, { size: 14 }) : /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(import_lucide_react5.ImageIcon, { size: 14 }),
|
|
9398
|
-
|
|
9675
|
+
replaceLabel
|
|
9399
9676
|
]
|
|
9400
9677
|
}
|
|
9401
9678
|
),
|
|
9402
|
-
replaceMode
|
|
9679
|
+
showChrome && replaceMode !== "none" && /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(
|
|
9403
9680
|
Button,
|
|
9404
9681
|
{
|
|
9405
9682
|
"data-ohw-media-overlay": "",
|
|
9406
9683
|
variant: "outline",
|
|
9407
9684
|
size: "sm",
|
|
9408
|
-
"aria-label":
|
|
9685
|
+
"aria-label": replaceLabel,
|
|
9409
9686
|
className: "gap-1.5 cursor-pointer hover:bg-background",
|
|
9410
9687
|
style: {
|
|
9411
9688
|
...OVERLAY_BUTTON_STYLE,
|
|
@@ -9428,7 +9705,7 @@ function MediaOverlay({
|
|
|
9428
9705
|
},
|
|
9429
9706
|
children: [
|
|
9430
9707
|
isVideo ? /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(import_lucide_react5.Film, { size: 14 }) : /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(import_lucide_react5.ImageIcon, { size: 14 }),
|
|
9431
|
-
replaceMode === "full" ?
|
|
9708
|
+
replaceMode === "full" ? replaceLabel : null
|
|
9432
9709
|
]
|
|
9433
9710
|
}
|
|
9434
9711
|
)
|
|
@@ -11255,6 +11532,13 @@ function findButtonAtPoint(x, y, media) {
|
|
|
11255
11532
|
if (hits.length === 0) return null;
|
|
11256
11533
|
return hits.reduce((best, el) => best.contains(el) ? el : best);
|
|
11257
11534
|
}
|
|
11535
|
+
function findNavbarCtaAtPoint(x, y) {
|
|
11536
|
+
const hits = Array.from(
|
|
11537
|
+
document.querySelectorAll('[data-ohw-role="navbar-button"]')
|
|
11538
|
+
).filter((el) => containsPoint(el, x, y) && !el.closest("[data-ohw-bridge]"));
|
|
11539
|
+
if (hits.length === 0) return null;
|
|
11540
|
+
return hits.reduce((best, el) => best.contains(el) ? el : best);
|
|
11541
|
+
}
|
|
11258
11542
|
|
|
11259
11543
|
// src/lib/session-search.ts
|
|
11260
11544
|
var STORAGE_KEY = "ohw-preserved-search";
|
|
@@ -11990,6 +12274,26 @@ var import_react12 = require("react");
|
|
|
11990
12274
|
var import_react_dom3 = require("react-dom");
|
|
11991
12275
|
var import_lucide_react15 = require("lucide-react");
|
|
11992
12276
|
var import_navigation2 = require("next/navigation");
|
|
12277
|
+
|
|
12278
|
+
// src/lib/parent-scroll.ts
|
|
12279
|
+
function visibleBand(parentScroll) {
|
|
12280
|
+
const { iframeOffsetTop, headerH: visibleCanvasTop, canvasH } = parentScroll;
|
|
12281
|
+
const top = Math.max(0, visibleCanvasTop - iframeOffsetTop);
|
|
12282
|
+
const bottom = Math.min(window.innerHeight, visibleCanvasTop + canvasH - iframeOffsetTop);
|
|
12283
|
+
return { top, bottom: Math.max(top, bottom) };
|
|
12284
|
+
}
|
|
12285
|
+
function getIframeVisibleClip(parentScroll) {
|
|
12286
|
+
if (!parentScroll) return null;
|
|
12287
|
+
return visibleBand(parentScroll);
|
|
12288
|
+
}
|
|
12289
|
+
function getIframeChromeClip(parentScroll) {
|
|
12290
|
+
if (!parentScroll) return null;
|
|
12291
|
+
const band = visibleBand(parentScroll);
|
|
12292
|
+
const promptBarH = Math.max(0, parentScroll.promptBarH ?? 0);
|
|
12293
|
+
return { top: band.top, bottom: Math.max(band.top, band.bottom - promptBarH) };
|
|
12294
|
+
}
|
|
12295
|
+
|
|
12296
|
+
// src/ui/link-modal/SectionPickerOverlay.tsx
|
|
11993
12297
|
var import_jsx_runtime27 = require("react/jsx-runtime");
|
|
11994
12298
|
var DIM_OVERLAY = "rgba(0, 0, 0, 0.45)";
|
|
11995
12299
|
function rectsEqual(a, b) {
|
|
@@ -12127,20 +12431,22 @@ function SectionPickerOverlay({
|
|
|
12127
12431
|
[]
|
|
12128
12432
|
);
|
|
12129
12433
|
(0, import_react12.useEffect)(() => {
|
|
12130
|
-
const applyClip = (iframeOffsetTop, visibleCanvasTop, canvasH) => {
|
|
12131
|
-
const
|
|
12132
|
-
|
|
12133
|
-
|
|
12134
|
-
|
|
12135
|
-
|
|
12434
|
+
const applyClip = (iframeOffsetTop, visibleCanvasTop, canvasH, promptBarH = 0) => {
|
|
12435
|
+
const next = getIframeVisibleClip({
|
|
12436
|
+
iframeOffsetTop,
|
|
12437
|
+
headerH: visibleCanvasTop,
|
|
12438
|
+
canvasH,
|
|
12439
|
+
promptBarH
|
|
12440
|
+
});
|
|
12441
|
+
if (!next) return;
|
|
12136
12442
|
setChromeClip(
|
|
12137
|
-
(prev) => prev.top === top && prev.bottom === bottom ? prev :
|
|
12443
|
+
(prev) => prev.top === next.top && prev.bottom === next.bottom ? prev : next
|
|
12138
12444
|
);
|
|
12139
12445
|
};
|
|
12140
12446
|
const onParentScroll = (e) => {
|
|
12141
12447
|
if (e.data?.type !== "ow:parent-scroll") return;
|
|
12142
|
-
const { iframeOffsetTop, headerH, canvasH } = e.data;
|
|
12143
|
-
applyClip(iframeOffsetTop, headerH, canvasH);
|
|
12448
|
+
const { iframeOffsetTop, headerH, canvasH, promptBarH = 0 } = e.data;
|
|
12449
|
+
applyClip(iframeOffsetTop, headerH, canvasH, promptBarH);
|
|
12144
12450
|
iframeOffsetTopRef.current = iframeOffsetTop;
|
|
12145
12451
|
if (!pointerScreenRef.current && pointerRef.current) {
|
|
12146
12452
|
pointerScreenRef.current = {
|
|
@@ -15733,6 +16039,7 @@ function readLogoSizeState(content, placement) {
|
|
|
15733
16039
|
function getLogoElement(el) {
|
|
15734
16040
|
const marked = el.closest('[data-ohw-role="logo"], [data-ohw-logo]');
|
|
15735
16041
|
if (marked) return marked;
|
|
16042
|
+
if (el.closest('[data-ohw-editable="icon"]')) return null;
|
|
15736
16043
|
const root = el.closest("nav, [data-ohw-nav-root], footer");
|
|
15737
16044
|
if (!root) return null;
|
|
15738
16045
|
const anchor = el.closest("a");
|
|
@@ -15804,36 +16111,50 @@ var import_lucide_react16 = require("lucide-react");
|
|
|
15804
16111
|
var import_jsx_runtime29 = require("react/jsx-runtime");
|
|
15805
16112
|
var PANEL_WIDTH = 256;
|
|
15806
16113
|
var EDGE_MARGIN = 16;
|
|
16114
|
+
var HEADER_MIN = 56;
|
|
15807
16115
|
function getVisibleClip(parentScroll) {
|
|
15808
16116
|
const left = 0;
|
|
15809
16117
|
const right = window.innerWidth;
|
|
15810
|
-
|
|
16118
|
+
const band = getIframeChromeClip(parentScroll);
|
|
16119
|
+
if (!band) {
|
|
15811
16120
|
return { top: 0, bottom: window.innerHeight, left, right };
|
|
15812
16121
|
}
|
|
15813
|
-
|
|
15814
|
-
const top = Math.max(0, visibleCanvasTop - iframeOffsetTop);
|
|
15815
|
-
const bottom = Math.min(window.innerHeight, visibleCanvasTop + canvasH - iframeOffsetTop);
|
|
15816
|
-
return { top, bottom: Math.max(top, bottom), left, right };
|
|
16122
|
+
return { ...band, left, right };
|
|
15817
16123
|
}
|
|
15818
|
-
function defaultFloatingPanelPosition(parentScroll,
|
|
16124
|
+
function defaultFloatingPanelPosition(parentScroll, _panelHeight = 280) {
|
|
15819
16125
|
const clip = getVisibleClip(parentScroll);
|
|
15820
16126
|
return {
|
|
15821
16127
|
x: Math.max(EDGE_MARGIN, clip.right - PANEL_WIDTH - EDGE_MARGIN),
|
|
15822
|
-
y:
|
|
15823
|
-
Math.max(clip.top + EDGE_MARGIN, EDGE_MARGIN),
|
|
15824
|
-
Math.max(clip.top + EDGE_MARGIN, clip.bottom - panelHeight - EDGE_MARGIN)
|
|
15825
|
-
)
|
|
16128
|
+
y: clip.top + EDGE_MARGIN
|
|
15826
16129
|
};
|
|
15827
16130
|
}
|
|
15828
|
-
function
|
|
16131
|
+
function clampX(x, panelW) {
|
|
16132
|
+
const left = EDGE_MARGIN;
|
|
16133
|
+
const maxX = Math.max(left, window.innerWidth - panelW - EDGE_MARGIN);
|
|
16134
|
+
return Math.min(Math.max(x, left), maxX);
|
|
16135
|
+
}
|
|
16136
|
+
function clampDragPosition(pos, parentScroll, panelW) {
|
|
15829
16137
|
const clip = getVisibleClip(parentScroll);
|
|
15830
|
-
const
|
|
15831
|
-
const maxY = Math.max(
|
|
16138
|
+
const minY = clip.top + EDGE_MARGIN;
|
|
16139
|
+
const maxY = Math.max(minY, clip.bottom - EDGE_MARGIN - HEADER_MIN);
|
|
15832
16140
|
return {
|
|
15833
|
-
x:
|
|
15834
|
-
y: Math.min(Math.max(pos.y,
|
|
16141
|
+
x: clampX(pos.x, panelW),
|
|
16142
|
+
y: Math.min(Math.max(pos.y, minY), maxY)
|
|
15835
16143
|
};
|
|
15836
16144
|
}
|
|
16145
|
+
function fitPanelInClip(homeY, parentScroll, preferredHeight) {
|
|
16146
|
+
const clip = getVisibleClip(parentScroll);
|
|
16147
|
+
const minY = clip.top + EDGE_MARGIN;
|
|
16148
|
+
const maxBottom = clip.bottom - EDGE_MARGIN;
|
|
16149
|
+
const band = Math.max(HEADER_MIN, maxBottom - minY);
|
|
16150
|
+
let y = Math.max(homeY, minY);
|
|
16151
|
+
const want = Math.min(Math.max(preferredHeight, HEADER_MIN), band);
|
|
16152
|
+
if (y + want > maxBottom) {
|
|
16153
|
+
y = Math.max(minY, maxBottom - want);
|
|
16154
|
+
}
|
|
16155
|
+
const maxHeight = Math.max(HEADER_MIN, Math.floor(maxBottom - y));
|
|
16156
|
+
return { y, maxHeight };
|
|
16157
|
+
}
|
|
15837
16158
|
function FloatingPanel({
|
|
15838
16159
|
open,
|
|
15839
16160
|
title,
|
|
@@ -15850,19 +16171,54 @@ function FloatingPanel({
|
|
|
15850
16171
|
const panelRef = (0, import_react15.useRef)(null);
|
|
15851
16172
|
const [measured, setMeasured] = (0, import_react15.useState)({ w: PANEL_WIDTH, h: 280 });
|
|
15852
16173
|
const dragRef = (0, import_react15.useRef)(null);
|
|
15853
|
-
const
|
|
15854
|
-
|
|
16174
|
+
const homeRef = (0, import_react15.useRef)(null);
|
|
16175
|
+
if (!open) {
|
|
16176
|
+
homeRef.current = null;
|
|
16177
|
+
} else if (position) {
|
|
16178
|
+
homeRef.current = position;
|
|
16179
|
+
} else if (homeRef.current == null) {
|
|
16180
|
+
homeRef.current = defaultFloatingPanelPosition(parentScroll);
|
|
16181
|
+
}
|
|
16182
|
+
const [liveScroll, setLiveScroll] = (0, import_react15.useState)(parentScroll);
|
|
16183
|
+
const home = position ?? homeRef.current ?? defaultFloatingPanelPosition(parentScroll);
|
|
16184
|
+
const { y: fittedY, maxHeight } = fitPanelInClip(home.y, liveScroll, measured.h);
|
|
16185
|
+
const clamped = {
|
|
16186
|
+
x: clampX(home.x, measured.w),
|
|
16187
|
+
y: fittedY
|
|
16188
|
+
};
|
|
16189
|
+
(0, import_react15.useEffect)(() => {
|
|
16190
|
+
setLiveScroll(parentScroll);
|
|
16191
|
+
}, [parentScroll]);
|
|
16192
|
+
(0, import_react15.useEffect)(() => {
|
|
16193
|
+
if (!open) return;
|
|
16194
|
+
const onParentScroll = (e) => {
|
|
16195
|
+
if (e.data?.type !== "ow:parent-scroll") return;
|
|
16196
|
+
const { iframeOffsetTop, headerH, canvasH, promptBarH = 0 } = e.data;
|
|
16197
|
+
setLiveScroll({ iframeOffsetTop, headerH, canvasH, promptBarH });
|
|
16198
|
+
};
|
|
16199
|
+
window.addEventListener("message", onParentScroll);
|
|
16200
|
+
return () => window.removeEventListener("message", onParentScroll);
|
|
16201
|
+
}, [open]);
|
|
16202
|
+
const positionRef = (0, import_react15.useRef)(position);
|
|
16203
|
+
(0, import_react15.useLayoutEffect)(() => {
|
|
16204
|
+
if (!open) {
|
|
16205
|
+
positionRef.current = position;
|
|
16206
|
+
return;
|
|
16207
|
+
}
|
|
16208
|
+
if (position == null && positionRef.current != null) {
|
|
16209
|
+
homeRef.current = defaultFloatingPanelPosition(liveScroll ?? parentScroll);
|
|
16210
|
+
}
|
|
16211
|
+
positionRef.current = position;
|
|
16212
|
+
}, [open, position, liveScroll, parentScroll]);
|
|
15855
16213
|
(0, import_react15.useLayoutEffect)(() => {
|
|
15856
16214
|
if (!open || !panelRef.current) return;
|
|
15857
16215
|
const el = panelRef.current;
|
|
15858
|
-
const
|
|
16216
|
+
const header = el.querySelector("[data-ohw-floating-panel-header]");
|
|
16217
|
+
const body = el.querySelector("[data-ohw-floating-panel-body]");
|
|
16218
|
+
const contentH = (header?.offsetHeight ?? 0) + (body?.scrollHeight ?? 0) || el.scrollHeight || 280;
|
|
16219
|
+
const next = { w: el.offsetWidth || PANEL_WIDTH, h: contentH };
|
|
15859
16220
|
setMeasured((prev) => prev.w === next.w && prev.h === next.h ? prev : next);
|
|
15860
16221
|
}, [open, children, title, context]);
|
|
15861
|
-
(0, import_react15.useEffect)(() => {
|
|
15862
|
-
if (!open || !position || !onPositionChange) return;
|
|
15863
|
-
const next = clampPosition(position, parentScroll, measured.w, measured.h);
|
|
15864
|
-
if (next.x !== position.x || next.y !== position.y) onPositionChange(next);
|
|
15865
|
-
}, [open, parentScroll, measured.w, measured.h, position, onPositionChange]);
|
|
15866
16222
|
const onHeaderPointerDown = (0, import_react15.useCallback)(
|
|
15867
16223
|
(e) => {
|
|
15868
16224
|
if (e.button !== 0) return;
|
|
@@ -15896,18 +16252,17 @@ function FloatingPanel({
|
|
|
15896
16252
|
return;
|
|
15897
16253
|
}
|
|
15898
16254
|
e.preventDefault();
|
|
15899
|
-
const next =
|
|
16255
|
+
const next = clampDragPosition(
|
|
15900
16256
|
{
|
|
15901
16257
|
x: drag.originX + (e.clientX - drag.startX),
|
|
15902
16258
|
y: drag.originY + (e.clientY - drag.startY)
|
|
15903
16259
|
},
|
|
15904
|
-
|
|
15905
|
-
measured.w
|
|
15906
|
-
measured.h
|
|
16260
|
+
liveScroll,
|
|
16261
|
+
measured.w
|
|
15907
16262
|
);
|
|
15908
16263
|
onPositionChange?.(next);
|
|
15909
16264
|
},
|
|
15910
|
-
[measured.
|
|
16265
|
+
[measured.w, onPositionChange, liveScroll]
|
|
15911
16266
|
);
|
|
15912
16267
|
const endDrag = (0, import_react15.useCallback)((e) => {
|
|
15913
16268
|
const drag = dragRef.current;
|
|
@@ -15937,7 +16292,7 @@ function FloatingPanel({
|
|
|
15937
16292
|
"fixed z-[2147483647] flex w-64 flex-col overflow-hidden rounded-xl border border-border bg-background font-sans shadow-lg outline-none",
|
|
15938
16293
|
className
|
|
15939
16294
|
),
|
|
15940
|
-
style: { left: clamped.x, top: clamped.y },
|
|
16295
|
+
style: { left: clamped.x, top: clamped.y, maxHeight },
|
|
15941
16296
|
onMouseDown: (e) => e.stopPropagation(),
|
|
15942
16297
|
onPointerDown: (e) => e.stopPropagation(),
|
|
15943
16298
|
onClick: (e) => e.stopPropagation(),
|
|
@@ -15946,7 +16301,7 @@ function FloatingPanel({
|
|
|
15946
16301
|
"div",
|
|
15947
16302
|
{
|
|
15948
16303
|
"data-ohw-floating-panel-header": "",
|
|
15949
|
-
className: "relative flex cursor-grab items-start gap-2 border-b border-border py-
|
|
16304
|
+
className: "relative flex shrink-0 cursor-grab items-start gap-2 border-b border-border py-4! pl-5! pr-11! active:cursor-grabbing",
|
|
15950
16305
|
onPointerDown: onHeaderPointerDown,
|
|
15951
16306
|
onPointerMove: onHeaderPointerMove,
|
|
15952
16307
|
onPointerUp: endDrag,
|
|
@@ -15981,7 +16336,11 @@ function FloatingPanel({
|
|
|
15981
16336
|
"div",
|
|
15982
16337
|
{
|
|
15983
16338
|
"data-ohw-floating-panel-body": "",
|
|
15984
|
-
className: cn(
|
|
16339
|
+
className: cn(
|
|
16340
|
+
"flex min-h-0 w-full flex-1 flex-col gap-4 overflow-y-auto overscroll-contain p-4",
|
|
16341
|
+
bodyClassName
|
|
16342
|
+
),
|
|
16343
|
+
style: { WebkitOverflowScrolling: "touch" },
|
|
15985
16344
|
children
|
|
15986
16345
|
}
|
|
15987
16346
|
)
|
|
@@ -16059,121 +16418,1555 @@ function SocialsDisplayPanel({ display, onChange, className }) {
|
|
|
16059
16418
|
] });
|
|
16060
16419
|
}
|
|
16061
16420
|
|
|
16062
|
-
// src/
|
|
16063
|
-
|
|
16064
|
-
|
|
16065
|
-
|
|
16066
|
-
|
|
16421
|
+
// src/ui/button-style-panel.tsx
|
|
16422
|
+
var import_lucide_react17 = require("lucide-react");
|
|
16423
|
+
|
|
16424
|
+
// src/lib/button-styles.ts
|
|
16425
|
+
var BUTTON_VARIANTS_KEY = "__ohw_button_variants";
|
|
16426
|
+
var BUTTON_SIZES_KEY = "__ohw_button_sizes";
|
|
16427
|
+
var BUTTON_ASSIGNMENTS_KEY = "__ohw_button_assignments";
|
|
16428
|
+
var BUTTON_VARIANT_IDS = ["primary", "secondary", "ghost"];
|
|
16429
|
+
var BUTTON_SIZE_IDS = ["s", "m", "l"];
|
|
16430
|
+
var TRANSPARENT = "rgba(0, 0, 0, 0)";
|
|
16431
|
+
var REFERENCE_SIZES = {
|
|
16432
|
+
s: { height: 40, paddingTop: 8, paddingRight: 16, paddingBottom: 8, paddingLeft: 16, fontSize: 15, borderRadius: 8, gap: 8 },
|
|
16433
|
+
m: { height: 48, paddingTop: 12, paddingRight: 24, paddingBottom: 12, paddingLeft: 24, fontSize: 15, borderRadius: 8, gap: 8 },
|
|
16434
|
+
l: { height: 56, paddingTop: 16, paddingRight: 32, paddingBottom: 16, paddingLeft: 32, fontSize: 15, borderRadius: 8, gap: 8 }
|
|
16435
|
+
};
|
|
16436
|
+
function buttonStyleContext(_el) {
|
|
16437
|
+
return "Button";
|
|
16438
|
+
}
|
|
16439
|
+
function previewSlotBackground(el) {
|
|
16440
|
+
let node = el.parentElement;
|
|
16441
|
+
while (node && node !== el.ownerDocument.documentElement) {
|
|
16442
|
+
if (node.closest("[data-ohw-bridge], [data-ohw-bridge-root]")) {
|
|
16443
|
+
node = node.parentElement;
|
|
16444
|
+
continue;
|
|
16445
|
+
}
|
|
16446
|
+
const bg = getComputedStyle(node).backgroundColor;
|
|
16447
|
+
const parsed = parseColor(bg);
|
|
16448
|
+
if (parsed && !isTransparent(parsed)) return bg;
|
|
16449
|
+
node = node.parentElement;
|
|
16450
|
+
}
|
|
16451
|
+
const root = el.ownerDocument.documentElement;
|
|
16452
|
+
const style = getComputedStyle(root);
|
|
16453
|
+
for (const name of ["--brand-surface", "--brand-background", "--ohw-brand-light", "--color-light"]) {
|
|
16454
|
+
const value = style.getPropertyValue(name).trim();
|
|
16455
|
+
if (value) return value;
|
|
16067
16456
|
}
|
|
16457
|
+
return "var(--brand-background, var(--ohw-brand-light, var(--color-light, #ffffff)))";
|
|
16068
16458
|
}
|
|
16069
|
-
function
|
|
16070
|
-
|
|
16071
|
-
|
|
16459
|
+
function buttonId(el) {
|
|
16460
|
+
if (!el) return null;
|
|
16461
|
+
const button = el.matches(CTA_BUTTON_SELECTOR) ? el : el.closest(CTA_BUTTON_SELECTOR);
|
|
16462
|
+
const id = button?.getAttribute("data-ohw-href-key")?.trim();
|
|
16463
|
+
return id || null;
|
|
16072
16464
|
}
|
|
16073
|
-
function
|
|
16074
|
-
|
|
16465
|
+
function isButtonVariantId(value) {
|
|
16466
|
+
return BUTTON_VARIANT_IDS.includes(value);
|
|
16075
16467
|
}
|
|
16076
|
-
function
|
|
16077
|
-
|
|
16078
|
-
document.documentElement.setAttribute("data-ohw-item-dragging", "");
|
|
16079
|
-
clearTextSelection();
|
|
16468
|
+
function isButtonSizeId(value) {
|
|
16469
|
+
return BUTTON_SIZE_IDS.includes(value);
|
|
16080
16470
|
}
|
|
16081
|
-
function
|
|
16082
|
-
const
|
|
16083
|
-
|
|
16084
|
-
document.documentElement.removeAttribute("data-ohw-item-dragging");
|
|
16085
|
-
if (wasDragging) clearTextSelection();
|
|
16471
|
+
function px(value) {
|
|
16472
|
+
const rounded = Math.round(value * 100) / 100;
|
|
16473
|
+
return `${rounded}px`;
|
|
16086
16474
|
}
|
|
16087
|
-
|
|
16088
|
-
|
|
16089
|
-
|
|
16090
|
-
|
|
16091
|
-
|
|
16092
|
-
|
|
16093
|
-
return listActiveNavbarItems(draggedEl).filter((el) => {
|
|
16094
|
-
const key = el.getAttribute("data-ohw-href-key");
|
|
16095
|
-
return isNavbarHrefKey(key) && !isNestedNavChild(el);
|
|
16096
|
-
});
|
|
16475
|
+
function parsePx(value, rootFont = 16) {
|
|
16476
|
+
if (!value) return 0;
|
|
16477
|
+
const n = parseFloat(value);
|
|
16478
|
+
if (!Number.isFinite(n)) return 0;
|
|
16479
|
+
if (value.trim().endsWith("rem") || value.trim().endsWith("em")) return n * rootFont;
|
|
16480
|
+
return n;
|
|
16097
16481
|
}
|
|
16098
|
-
function
|
|
16099
|
-
|
|
16100
|
-
|
|
16101
|
-
|
|
16102
|
-
const trigger = group.querySelector(":scope > [data-ohw-href-key]") ?? Array.from(group.querySelectorAll("[data-ohw-href-key]")).find(
|
|
16103
|
-
(el) => !el.closest("[data-ohw-nav-children]")
|
|
16104
|
-
) ?? null;
|
|
16105
|
-
const key = trigger?.getAttribute("data-ohw-href-key");
|
|
16106
|
-
return key && isNavbarHrefKey(key) ? key : null;
|
|
16482
|
+
function classifyHeight(height) {
|
|
16483
|
+
if (height < 44) return "s";
|
|
16484
|
+
if (height < 52) return "m";
|
|
16485
|
+
return "l";
|
|
16107
16486
|
}
|
|
16108
|
-
function
|
|
16109
|
-
|
|
16110
|
-
|
|
16111
|
-
|
|
16112
|
-
|
|
16113
|
-
|
|
16114
|
-
|
|
16115
|
-
|
|
16116
|
-
(
|
|
16117
|
-
|
|
16487
|
+
function scaleGeometry(geometry, scale = 0.75) {
|
|
16488
|
+
return {
|
|
16489
|
+
paddingTop: px(parsePx(geometry.paddingTop) * scale),
|
|
16490
|
+
paddingRight: px(parsePx(geometry.paddingRight) * scale),
|
|
16491
|
+
paddingBottom: px(parsePx(geometry.paddingBottom) * scale),
|
|
16492
|
+
paddingLeft: px(parsePx(geometry.paddingLeft) * scale),
|
|
16493
|
+
fontSize: px(parsePx(geometry.fontSize) * scale),
|
|
16494
|
+
borderRadius: px(parsePx(geometry.borderRadius) * scale),
|
|
16495
|
+
gap: px(parsePx(geometry.gap) * scale),
|
|
16496
|
+
height: Math.round(geometry.height * scale)
|
|
16497
|
+
};
|
|
16118
16498
|
}
|
|
16119
|
-
function
|
|
16120
|
-
const
|
|
16121
|
-
|
|
16122
|
-
|
|
16123
|
-
|
|
16124
|
-
|
|
16125
|
-
|
|
16126
|
-
|
|
16499
|
+
function relativeLuminance(color) {
|
|
16500
|
+
const channel = (value) => {
|
|
16501
|
+
const s = value / 255;
|
|
16502
|
+
return s <= 0.03928 ? s / 12.92 : ((s + 0.055) / 1.055) ** 2.4;
|
|
16503
|
+
};
|
|
16504
|
+
return 0.2126 * channel(color.r) + 0.7152 * channel(color.g) + 0.0722 * channel(color.b);
|
|
16505
|
+
}
|
|
16506
|
+
function contrastRatio(a, b) {
|
|
16507
|
+
const lighter = Math.max(relativeLuminance(a), relativeLuminance(b));
|
|
16508
|
+
const darker = Math.min(relativeLuminance(a), relativeLuminance(b));
|
|
16509
|
+
return (lighter + 0.05) / (darker + 0.05);
|
|
16510
|
+
}
|
|
16511
|
+
function compositeOver(fg, bg) {
|
|
16512
|
+
const a = fg.a + bg.a * (1 - fg.a);
|
|
16513
|
+
if (a < 1e-3) return { ...bg, a: 0 };
|
|
16514
|
+
return {
|
|
16515
|
+
r: (fg.r * fg.a + bg.r * bg.a * (1 - fg.a)) / a,
|
|
16516
|
+
g: (fg.g * fg.a + bg.g * bg.a * (1 - fg.a)) / a,
|
|
16517
|
+
b: (fg.b * fg.a + bg.b * bg.a * (1 - fg.a)) / a,
|
|
16518
|
+
a
|
|
16519
|
+
};
|
|
16520
|
+
}
|
|
16521
|
+
function previewSlotForChrome(chrome, slotBackground) {
|
|
16522
|
+
const text = parseColor(chrome.color);
|
|
16523
|
+
if (!text || text.a < 0.2) return slotBackground;
|
|
16524
|
+
const slot = parseColor(slotBackground) ?? { r: 250, g: 250, b: 249, a: 1 };
|
|
16525
|
+
const fill = parseColor(chrome.background);
|
|
16526
|
+
const effective = fill && !isTransparent(fill) ? compositeOver(fill, slot) : slot;
|
|
16527
|
+
if (contrastRatio(text, effective) >= 3) return slotBackground;
|
|
16528
|
+
return relativeLuminance(text) > 0.55 ? "#2c2c2c" : "#f4f4f5";
|
|
16529
|
+
}
|
|
16530
|
+
function parseColor(input) {
|
|
16531
|
+
if (!input) return null;
|
|
16532
|
+
const value = input.trim().toLowerCase();
|
|
16533
|
+
if (value === "transparent") return { r: 0, g: 0, b: 0, a: 0 };
|
|
16534
|
+
const hex = value.match(/^#([0-9a-f]{3,8})$/);
|
|
16535
|
+
if (hex) {
|
|
16536
|
+
const raw = hex[1];
|
|
16537
|
+
const expand = (pair) => parseInt(pair.length === 1 ? pair + pair : pair, 16);
|
|
16538
|
+
if (raw.length === 3 || raw.length === 4) {
|
|
16539
|
+
return {
|
|
16540
|
+
r: expand(raw[0]),
|
|
16541
|
+
g: expand(raw[1]),
|
|
16542
|
+
b: expand(raw[2]),
|
|
16543
|
+
a: raw.length === 4 ? expand(raw[3]) / 255 : 1
|
|
16544
|
+
};
|
|
16545
|
+
}
|
|
16546
|
+
if (raw.length === 6 || raw.length === 8) {
|
|
16547
|
+
return {
|
|
16548
|
+
r: expand(raw.slice(0, 2)),
|
|
16549
|
+
g: expand(raw.slice(2, 4)),
|
|
16550
|
+
b: expand(raw.slice(4, 6)),
|
|
16551
|
+
a: raw.length === 8 ? expand(raw.slice(6, 8)) / 255 : 1
|
|
16552
|
+
};
|
|
16553
|
+
}
|
|
16127
16554
|
}
|
|
16128
|
-
const
|
|
16129
|
-
|
|
16130
|
-
|
|
16131
|
-
|
|
16555
|
+
const rgb = value.match(
|
|
16556
|
+
/^rgba?\(\s*([\d.]+)[%\s,]+([\d.]+)[%\s,]+([\d.]+)(?:%?\s*[,/]\s*([\d.]+%?))?\s*\)$/
|
|
16557
|
+
);
|
|
16558
|
+
if (rgb) {
|
|
16559
|
+
const alphaRaw = rgb[4];
|
|
16560
|
+
const alpha = alphaRaw == null ? 1 : alphaRaw.endsWith("%") ? parseFloat(alphaRaw) / 100 : parseFloat(alphaRaw);
|
|
16561
|
+
return { r: Number(rgb[1]), g: Number(rgb[2]), b: Number(rgb[3]), a: alpha };
|
|
16562
|
+
}
|
|
16563
|
+
const oklch = value.match(
|
|
16564
|
+
/^oklch\(\s*([\d.]+%?)\s+([\d.]+)\s+([\d.]+)(?:deg)?(?:\s*\/\s*([\d.]+%?))?\s*\)$/
|
|
16565
|
+
);
|
|
16566
|
+
if (oklch) {
|
|
16567
|
+
const Lraw = oklch[1];
|
|
16568
|
+
const L = Lraw.endsWith("%") ? parseFloat(Lraw) / 100 : parseFloat(Lraw);
|
|
16569
|
+
const gray = Math.max(0, Math.min(1, L)) * 255;
|
|
16570
|
+
const alphaRaw = oklch[4];
|
|
16571
|
+
const alpha = alphaRaw == null ? 1 : alphaRaw.endsWith("%") ? parseFloat(alphaRaw) / 100 : parseFloat(alphaRaw);
|
|
16572
|
+
return { r: gray, g: gray, b: gray, a: alpha };
|
|
16573
|
+
}
|
|
16574
|
+
return null;
|
|
16132
16575
|
}
|
|
16133
|
-
function
|
|
16134
|
-
|
|
16135
|
-
|
|
16136
|
-
|
|
16137
|
-
|
|
16138
|
-
|
|
16139
|
-
|
|
16140
|
-
|
|
16141
|
-
insertIndex: 0,
|
|
16142
|
-
parentId: null,
|
|
16143
|
-
left: rect.left,
|
|
16144
|
-
top: rect.top + rect.height / 2 - barThickness / 2,
|
|
16145
|
-
width: Math.max(rect.width, 40),
|
|
16146
|
-
height: barThickness,
|
|
16147
|
-
direction: "horizontal"
|
|
16148
|
-
});
|
|
16149
|
-
return slots;
|
|
16576
|
+
function isTransparent(color) {
|
|
16577
|
+
return !color || color.a < 0.05;
|
|
16578
|
+
}
|
|
16579
|
+
function hasOpaqueBackground(background) {
|
|
16580
|
+
if (!background) return false;
|
|
16581
|
+
const value = background.trim().toLowerCase();
|
|
16582
|
+
if (!value || value === "transparent" || value === "rgba(0, 0, 0, 0)" || value === "rgb(0, 0, 0, 0)") {
|
|
16583
|
+
return false;
|
|
16150
16584
|
}
|
|
16151
|
-
const
|
|
16152
|
-
|
|
16153
|
-
|
|
16154
|
-
|
|
16155
|
-
|
|
16156
|
-
|
|
16157
|
-
|
|
16158
|
-
|
|
16159
|
-
|
|
16160
|
-
|
|
16161
|
-
|
|
16162
|
-
|
|
16163
|
-
|
|
16164
|
-
|
|
16165
|
-
|
|
16166
|
-
|
|
16167
|
-
|
|
16168
|
-
|
|
16169
|
-
|
|
16170
|
-
|
|
16171
|
-
|
|
16172
|
-
|
|
16173
|
-
|
|
16174
|
-
|
|
16175
|
-
|
|
16176
|
-
|
|
16585
|
+
const parsed = parseColor(background);
|
|
16586
|
+
if (parsed) return !isTransparent(parsed);
|
|
16587
|
+
return true;
|
|
16588
|
+
}
|
|
16589
|
+
function toCss(color) {
|
|
16590
|
+
const r2 = Math.round(color.r);
|
|
16591
|
+
const g = Math.round(color.g);
|
|
16592
|
+
const b = Math.round(color.b);
|
|
16593
|
+
if (color.a >= 0.995) return `rgb(${r2}, ${g}, ${b})`;
|
|
16594
|
+
return `rgba(${r2}, ${g}, ${b}, ${Math.round(color.a * 100) / 100})`;
|
|
16595
|
+
}
|
|
16596
|
+
function colorKey(input) {
|
|
16597
|
+
const parsed = parseColor(input);
|
|
16598
|
+
if (!parsed || isTransparent(parsed)) return "transparent";
|
|
16599
|
+
return `${Math.round(parsed.r / 8)}-${Math.round(parsed.g / 8)}-${Math.round(parsed.b / 8)}-${Math.round(parsed.a * 4)}`;
|
|
16600
|
+
}
|
|
16601
|
+
function declaredVariant(className) {
|
|
16602
|
+
const match = className.match(/\bbtn--(primary|secondary|ghost)\b/);
|
|
16603
|
+
return match && isButtonVariantId(match[1]) ? match[1] : null;
|
|
16604
|
+
}
|
|
16605
|
+
function fillSlot(sample) {
|
|
16606
|
+
const width = parseFloat(sample.borderWidth);
|
|
16607
|
+
const border = parseColor(sample.borderColor);
|
|
16608
|
+
if (width > 0 && !isTransparent(border)) return "secondary";
|
|
16609
|
+
if (hasOpaqueBackground(sample.background)) return "primary";
|
|
16610
|
+
return "ghost";
|
|
16611
|
+
}
|
|
16612
|
+
function sampleSlot(sample) {
|
|
16613
|
+
return declaredVariant(sample.className) ?? fillSlot(sample);
|
|
16614
|
+
}
|
|
16615
|
+
function fingerprint(sample) {
|
|
16616
|
+
const width = parseFloat(sample.borderWidth);
|
|
16617
|
+
const border = width > 0 ? colorKey(sample.borderColor) : "none";
|
|
16618
|
+
return `${colorKey(sample.background)}|${border}|${colorKey(sample.color)}|${sampleSlot(sample)}`;
|
|
16619
|
+
}
|
|
16620
|
+
function paintColor(chrome) {
|
|
16621
|
+
if (hasOpaqueBackground(chrome.background)) {
|
|
16622
|
+
const parsed = parseColor(chrome.background);
|
|
16623
|
+
return parsed ? toCss({ ...parsed, a: 1 }) : chrome.background;
|
|
16624
|
+
}
|
|
16625
|
+
const width = parseFloat(chrome.borderWidth);
|
|
16626
|
+
if (width > 0 && hasOpaqueBackground(chrome.borderColor)) {
|
|
16627
|
+
const parsed = parseColor(chrome.borderColor);
|
|
16628
|
+
return parsed ? toCss({ ...parsed, a: 1 }) : chrome.borderColor;
|
|
16629
|
+
}
|
|
16630
|
+
const text = parseColor(chrome.color);
|
|
16631
|
+
return text ? toCss({ ...text, a: 1 }) : chrome.color;
|
|
16632
|
+
}
|
|
16633
|
+
function accentColor(chrome) {
|
|
16634
|
+
const bg = parseColor(chrome.background);
|
|
16635
|
+
if (bg && !isTransparent(bg) && relativeLuminance(bg) < 0.55) {
|
|
16636
|
+
return toCss({ ...bg, a: 1 });
|
|
16637
|
+
}
|
|
16638
|
+
const text = parseColor(chrome.color);
|
|
16639
|
+
if (text && !isTransparent(text)) return toCss({ ...text, a: 1 });
|
|
16640
|
+
return paintColor(chrome);
|
|
16641
|
+
}
|
|
16642
|
+
function chromeFrom(sample) {
|
|
16643
|
+
return {
|
|
16644
|
+
background: sample.background || TRANSPARENT,
|
|
16645
|
+
color: sample.color || "currentColor",
|
|
16646
|
+
borderColor: sample.borderColor || TRANSPARENT,
|
|
16647
|
+
borderWidth: sample.borderWidth || "0px"
|
|
16648
|
+
};
|
|
16649
|
+
}
|
|
16650
|
+
function filledPrimary(seed) {
|
|
16651
|
+
const paint = parseColor(paintColor(seed)) ?? { r: 15, g: 15, b: 15, a: 1 };
|
|
16652
|
+
const luminance = relativeLuminance(paint);
|
|
16653
|
+
return {
|
|
16654
|
+
background: toCss({ ...paint, a: 1 }),
|
|
16655
|
+
color: luminance > 0.55 ? "rgb(15, 15, 15)" : "rgb(255, 255, 255)",
|
|
16656
|
+
borderColor: TRANSPARENT,
|
|
16657
|
+
borderWidth: "0px"
|
|
16658
|
+
};
|
|
16659
|
+
}
|
|
16660
|
+
function generatedSecondary(primary) {
|
|
16661
|
+
const paint = accentColor(primary);
|
|
16662
|
+
return {
|
|
16663
|
+
background: TRANSPARENT,
|
|
16664
|
+
color: paint,
|
|
16665
|
+
borderColor: paint,
|
|
16666
|
+
borderWidth: "1px"
|
|
16667
|
+
};
|
|
16668
|
+
}
|
|
16669
|
+
function generatedGhost(primary) {
|
|
16670
|
+
return {
|
|
16671
|
+
background: TRANSPARENT,
|
|
16672
|
+
color: accentColor(primary),
|
|
16673
|
+
borderColor: TRANSPARENT,
|
|
16674
|
+
borderWidth: "0px"
|
|
16675
|
+
};
|
|
16676
|
+
}
|
|
16677
|
+
function normalizeOutlineChrome(outline, primary) {
|
|
16678
|
+
const paint = accentColor(primary);
|
|
16679
|
+
const text = parseColor(outline.color);
|
|
16680
|
+
const paintRgb = parseColor(paint);
|
|
16681
|
+
const primaryLabel = parseColor(primary.color);
|
|
16682
|
+
const matchesOnPrimary = Boolean(text && primaryLabel) && colorKey(outline.color) === colorKey(primary.color);
|
|
16683
|
+
const textTooLight = text ? relativeLuminance(text) > 0.7 : false;
|
|
16684
|
+
const paintIsDarker = paintRgb ? relativeLuminance(paintRgb) < 0.65 : hasOpaqueBackground(primary.background);
|
|
16685
|
+
if (!(matchesOnPrimary || textTooLight) || !paintIsDarker) return outline;
|
|
16686
|
+
const hasBorder = parseFloat(outline.borderWidth) > 0;
|
|
16687
|
+
return {
|
|
16688
|
+
...outline,
|
|
16689
|
+
color: paint,
|
|
16690
|
+
borderColor: hasBorder ? paint : outline.borderColor
|
|
16691
|
+
};
|
|
16692
|
+
}
|
|
16693
|
+
function generateButtonVariants(samples) {
|
|
16694
|
+
if (samples.length === 0) return { status: "unresolved" };
|
|
16695
|
+
const groups = /* @__PURE__ */ new Map();
|
|
16696
|
+
for (const sample of samples) {
|
|
16697
|
+
const key = fingerprint(sample);
|
|
16698
|
+
const list = groups.get(key) ?? [];
|
|
16699
|
+
list.push(sample);
|
|
16700
|
+
groups.set(key, list);
|
|
16701
|
+
}
|
|
16702
|
+
if (groups.size > 3) return { status: "unresolved" };
|
|
16703
|
+
const bySlot = /* @__PURE__ */ new Map();
|
|
16704
|
+
for (const group of groups.values()) {
|
|
16705
|
+
const sample = group[0];
|
|
16706
|
+
const slot = sampleSlot(sample);
|
|
16707
|
+
if (bySlot.has(slot)) return { status: "unresolved" };
|
|
16708
|
+
bySlot.set(slot, sample);
|
|
16709
|
+
}
|
|
16710
|
+
const primarySample = bySlot.get("primary");
|
|
16711
|
+
const seed = chromeFrom(primarySample ?? samples[0]);
|
|
16712
|
+
const primary = primarySample ? seed : filledPrimary(seed);
|
|
16713
|
+
const secondary = normalizeOutlineChrome(
|
|
16714
|
+
bySlot.has("secondary") ? chromeFrom(bySlot.get("secondary")) : generatedSecondary(primary),
|
|
16715
|
+
primary
|
|
16716
|
+
);
|
|
16717
|
+
const ghost = normalizeOutlineChrome(
|
|
16718
|
+
bySlot.has("ghost") ? chromeFrom(bySlot.get("ghost")) : generatedGhost(primary),
|
|
16719
|
+
primary
|
|
16720
|
+
);
|
|
16721
|
+
return {
|
|
16722
|
+
status: "ready",
|
|
16723
|
+
tokens: { primary, secondary, ghost }
|
|
16724
|
+
};
|
|
16725
|
+
}
|
|
16726
|
+
function geometryFromSample(sample) {
|
|
16727
|
+
return {
|
|
16728
|
+
paddingTop: px(sample.paddingTop),
|
|
16729
|
+
paddingRight: px(sample.paddingRight),
|
|
16730
|
+
paddingBottom: px(sample.paddingBottom),
|
|
16731
|
+
paddingLeft: px(sample.paddingLeft),
|
|
16732
|
+
fontSize: px(sample.fontSize),
|
|
16733
|
+
borderRadius: px(sample.borderRadius),
|
|
16734
|
+
gap: px(sample.gap),
|
|
16735
|
+
height: Math.round(sample.height)
|
|
16736
|
+
};
|
|
16737
|
+
}
|
|
16738
|
+
function shiftSample(base, steps) {
|
|
16739
|
+
return {
|
|
16740
|
+
height: Math.max(24, base.height + steps * 8),
|
|
16741
|
+
paddingTop: Math.max(0, base.paddingTop + steps * 4),
|
|
16742
|
+
paddingBottom: Math.max(0, base.paddingBottom + steps * 4),
|
|
16743
|
+
paddingLeft: Math.max(0, base.paddingLeft + steps * 8),
|
|
16744
|
+
paddingRight: Math.max(0, base.paddingRight + steps * 8),
|
|
16745
|
+
fontSize: base.fontSize,
|
|
16746
|
+
borderRadius: base.borderRadius,
|
|
16747
|
+
gap: base.gap
|
|
16748
|
+
};
|
|
16749
|
+
}
|
|
16750
|
+
function clusterSizes(samples) {
|
|
16751
|
+
const sorted = [...samples].sort((a, b) => a.height - b.height);
|
|
16752
|
+
const clusters = [];
|
|
16753
|
+
for (const sample of sorted) {
|
|
16754
|
+
const current = clusters[clusters.length - 1];
|
|
16755
|
+
const head = current?.[0];
|
|
16756
|
+
if (!current || !head || Math.abs(sample.height - head.height) > 2) clusters.push([sample]);
|
|
16757
|
+
else current.push(sample);
|
|
16758
|
+
}
|
|
16759
|
+
return clusters.map((group) => {
|
|
16760
|
+
const pick = (key) => group.reduce((sum, item) => sum + item[key], 0) / group.length;
|
|
16761
|
+
return {
|
|
16762
|
+
height: pick("height"),
|
|
16763
|
+
paddingTop: pick("paddingTop"),
|
|
16764
|
+
paddingRight: pick("paddingRight"),
|
|
16765
|
+
paddingBottom: pick("paddingBottom"),
|
|
16766
|
+
paddingLeft: pick("paddingLeft"),
|
|
16767
|
+
fontSize: pick("fontSize"),
|
|
16768
|
+
borderRadius: pick("borderRadius"),
|
|
16769
|
+
gap: pick("gap")
|
|
16770
|
+
};
|
|
16771
|
+
});
|
|
16772
|
+
}
|
|
16773
|
+
function tokensFromSamples(bySlot, radius, gap) {
|
|
16774
|
+
const fill = (id) => {
|
|
16775
|
+
const sample = bySlot[id] ?? REFERENCE_SIZES[id];
|
|
16776
|
+
return geometryFromSample({ ...sample, borderRadius: radius, gap });
|
|
16777
|
+
};
|
|
16778
|
+
return { s: fill("s"), m: fill("m"), l: fill("l") };
|
|
16779
|
+
}
|
|
16780
|
+
function interpolateSizes(known) {
|
|
16781
|
+
const order = BUTTON_SIZE_IDS;
|
|
16782
|
+
const indexOf = (id) => order.indexOf(id);
|
|
16783
|
+
const sorted = [...known].sort((a, b) => indexOf(a.id) - indexOf(b.id));
|
|
16784
|
+
const left = sorted[0];
|
|
16785
|
+
const right = sorted[1];
|
|
16786
|
+
const span = indexOf(right.id) - indexOf(left.id);
|
|
16787
|
+
const step = (key) => (right.sample[key] - left.sample[key]) / span;
|
|
16788
|
+
const at = (index) => {
|
|
16789
|
+
const steps = index - indexOf(left.id);
|
|
16790
|
+
return {
|
|
16791
|
+
height: left.sample.height + step("height") * steps,
|
|
16792
|
+
paddingTop: Math.max(0, left.sample.paddingTop + step("paddingTop") * steps),
|
|
16793
|
+
paddingBottom: Math.max(0, left.sample.paddingBottom + step("paddingBottom") * steps),
|
|
16794
|
+
paddingLeft: Math.max(0, left.sample.paddingLeft + step("paddingLeft") * steps),
|
|
16795
|
+
paddingRight: Math.max(0, left.sample.paddingRight + step("paddingRight") * steps),
|
|
16796
|
+
fontSize: Math.max(10, left.sample.fontSize + step("fontSize") * steps),
|
|
16797
|
+
borderRadius: left.sample.borderRadius,
|
|
16798
|
+
gap: left.sample.gap
|
|
16799
|
+
};
|
|
16800
|
+
};
|
|
16801
|
+
const bySlot = {
|
|
16802
|
+
[left.id]: left.sample,
|
|
16803
|
+
[right.id]: { ...right.sample, borderRadius: left.sample.borderRadius, gap: left.sample.gap }
|
|
16804
|
+
};
|
|
16805
|
+
for (const id of order) {
|
|
16806
|
+
if (!bySlot[id]) bySlot[id] = at(indexOf(id));
|
|
16807
|
+
}
|
|
16808
|
+
return tokensFromSamples(bySlot, left.sample.borderRadius, left.sample.gap);
|
|
16809
|
+
}
|
|
16810
|
+
function generateButtonSizes(samples) {
|
|
16811
|
+
const clusters = clusterSizes(samples.filter((sample) => sample.height > 0));
|
|
16812
|
+
if (clusters.length === 0) {
|
|
16813
|
+
return { status: "ready", tokens: tokensFromSamples(REFERENCE_SIZES, 8, 8) };
|
|
16814
|
+
}
|
|
16815
|
+
if (clusters.length > 3) return { status: "unresolved" };
|
|
16816
|
+
if (clusters.length === 3) {
|
|
16817
|
+
const sorted = [...clusters].sort((a, b) => a.height - b.height);
|
|
16818
|
+
const radius = sorted[1].borderRadius;
|
|
16819
|
+
const gap = sorted[1].gap;
|
|
16820
|
+
return {
|
|
16821
|
+
status: "ready",
|
|
16822
|
+
tokens: {
|
|
16823
|
+
s: geometryFromSample({ ...sorted[0], borderRadius: radius, gap }),
|
|
16824
|
+
m: geometryFromSample({ ...sorted[1], borderRadius: radius, gap }),
|
|
16825
|
+
l: geometryFromSample({ ...sorted[2], borderRadius: radius, gap })
|
|
16826
|
+
}
|
|
16827
|
+
};
|
|
16828
|
+
}
|
|
16829
|
+
if (clusters.length === 1) {
|
|
16830
|
+
const known = clusters[0];
|
|
16831
|
+
const slot = classifyHeight(known.height);
|
|
16832
|
+
const offset = BUTTON_SIZE_IDS.indexOf(slot);
|
|
16833
|
+
const bySlot = Object.fromEntries(
|
|
16834
|
+
BUTTON_SIZE_IDS.map((id, index) => [id, shiftSample(known, index - offset)])
|
|
16835
|
+
);
|
|
16836
|
+
bySlot[slot] = known;
|
|
16837
|
+
return { status: "ready", tokens: tokensFromSamples(bySlot, known.borderRadius, known.gap) };
|
|
16838
|
+
}
|
|
16839
|
+
const mapped = clusters.map((sample) => ({ id: classifyHeight(sample.height), sample }));
|
|
16840
|
+
if (mapped[0].id === mapped[1].id) {
|
|
16841
|
+
const larger = clusters.slice().sort((a, b) => b.height - a.height)[0];
|
|
16842
|
+
return generateButtonSizes([larger]);
|
|
16843
|
+
}
|
|
16844
|
+
return { status: "ready", tokens: interpolateSizes(mapped) };
|
|
16845
|
+
}
|
|
16846
|
+
function parseJson(raw) {
|
|
16847
|
+
if (!raw) return null;
|
|
16848
|
+
try {
|
|
16849
|
+
return JSON.parse(raw);
|
|
16850
|
+
} catch {
|
|
16851
|
+
return null;
|
|
16852
|
+
}
|
|
16853
|
+
}
|
|
16854
|
+
function isChrome(value) {
|
|
16855
|
+
if (!value || typeof value !== "object") return false;
|
|
16856
|
+
const chrome = value;
|
|
16857
|
+
return typeof chrome.background === "string" && typeof chrome.color === "string";
|
|
16858
|
+
}
|
|
16859
|
+
function isGeometry(value) {
|
|
16860
|
+
if (!value || typeof value !== "object") return false;
|
|
16861
|
+
const geometry = value;
|
|
16862
|
+
return typeof geometry.paddingTop === "string" && typeof geometry.height === "number";
|
|
16863
|
+
}
|
|
16864
|
+
function readVariantTokens(content) {
|
|
16865
|
+
const parsed = parseJson(content[BUTTON_VARIANTS_KEY]);
|
|
16866
|
+
if (!parsed) return null;
|
|
16867
|
+
if (!BUTTON_VARIANT_IDS.every((id) => isChrome(parsed[id]))) return null;
|
|
16868
|
+
return parsed;
|
|
16869
|
+
}
|
|
16870
|
+
function readSizeTokens(content) {
|
|
16871
|
+
const parsed = parseJson(content[BUTTON_SIZES_KEY]);
|
|
16872
|
+
if (!parsed) return null;
|
|
16873
|
+
if (!BUTTON_SIZE_IDS.every((id) => isGeometry(parsed[id]))) return null;
|
|
16874
|
+
return parsed;
|
|
16875
|
+
}
|
|
16876
|
+
function readAssignments(content) {
|
|
16877
|
+
const parsed = parseJson(content[BUTTON_ASSIGNMENTS_KEY]);
|
|
16878
|
+
if (!parsed || typeof parsed !== "object") return {};
|
|
16879
|
+
const next = {};
|
|
16880
|
+
for (const [id, value] of Object.entries(parsed)) {
|
|
16881
|
+
if (!value || !isButtonVariantId(value.variant) || !isButtonSizeId(value.size)) continue;
|
|
16882
|
+
next[id] = { variant: value.variant, size: value.size };
|
|
16883
|
+
}
|
|
16884
|
+
return next;
|
|
16885
|
+
}
|
|
16886
|
+
function cssLength(style, prop) {
|
|
16887
|
+
return style.getPropertyValue(prop) || "0px";
|
|
16888
|
+
}
|
|
16889
|
+
function readVariantSample(el) {
|
|
16890
|
+
const style = getComputedStyle(el);
|
|
16891
|
+
return {
|
|
16892
|
+
background: style.backgroundColor,
|
|
16893
|
+
color: style.color,
|
|
16894
|
+
borderColor: style.borderTopColor,
|
|
16895
|
+
borderWidth: style.borderTopWidth,
|
|
16896
|
+
className: el.className || ""
|
|
16897
|
+
};
|
|
16898
|
+
}
|
|
16899
|
+
function readSizeSample(el) {
|
|
16900
|
+
const style = getComputedStyle(el);
|
|
16901
|
+
const rootFont = parsePx(getComputedStyle(el.ownerDocument.documentElement).fontSize) || 16;
|
|
16902
|
+
const rect = el.getBoundingClientRect();
|
|
16903
|
+
return {
|
|
16904
|
+
height: rect.height,
|
|
16905
|
+
paddingTop: parsePx(cssLength(style, "padding-top"), rootFont),
|
|
16906
|
+
paddingRight: parsePx(cssLength(style, "padding-right"), rootFont),
|
|
16907
|
+
paddingBottom: parsePx(cssLength(style, "padding-bottom"), rootFont),
|
|
16908
|
+
paddingLeft: parsePx(cssLength(style, "padding-left"), rootFont),
|
|
16909
|
+
fontSize: parsePx(style.fontSize, rootFont),
|
|
16910
|
+
borderRadius: parsePx(style.borderTopLeftRadius, rootFont),
|
|
16911
|
+
gap: parsePx(style.columnGap || style.gap, rootFont)
|
|
16912
|
+
};
|
|
16913
|
+
}
|
|
16914
|
+
function readTypography(el) {
|
|
16915
|
+
const style = getComputedStyle(el);
|
|
16916
|
+
return {
|
|
16917
|
+
fontFamily: style.fontFamily,
|
|
16918
|
+
fontWeight: style.fontWeight,
|
|
16919
|
+
letterSpacing: style.letterSpacing,
|
|
16920
|
+
textTransform: style.textTransform,
|
|
16921
|
+
textDecoration: style.textDecorationLine || style.textDecoration || "none"
|
|
16922
|
+
};
|
|
16923
|
+
}
|
|
16924
|
+
var buttonOriginByEl = /* @__PURE__ */ new WeakMap();
|
|
16925
|
+
var ORIGIN_ATTR = "data-ohw-btn-origin";
|
|
16926
|
+
function parseOriginAttr(raw) {
|
|
16927
|
+
if (!raw) return null;
|
|
16928
|
+
try {
|
|
16929
|
+
const value = JSON.parse(raw);
|
|
16930
|
+
if (!value?.variant || !value.size || !value.typography) return null;
|
|
16931
|
+
return value;
|
|
16932
|
+
} catch {
|
|
16933
|
+
return null;
|
|
16934
|
+
}
|
|
16935
|
+
}
|
|
16936
|
+
function measureLiveOrigin(el) {
|
|
16937
|
+
return {
|
|
16938
|
+
variant: readVariantSample(el),
|
|
16939
|
+
size: readSizeSample(el),
|
|
16940
|
+
typography: readTypography(el)
|
|
16941
|
+
};
|
|
16942
|
+
}
|
|
16943
|
+
function captureButtonOrigin(el) {
|
|
16944
|
+
const cached = buttonOriginByEl.get(el);
|
|
16945
|
+
if (cached) return cached;
|
|
16946
|
+
const fromAttr = parseOriginAttr(el.getAttribute(ORIGIN_ATTR));
|
|
16947
|
+
if (fromAttr) {
|
|
16948
|
+
buttonOriginByEl.set(el, fromAttr);
|
|
16949
|
+
return fromAttr;
|
|
16950
|
+
}
|
|
16951
|
+
const origin = measureLiveOrigin(el);
|
|
16952
|
+
buttonOriginByEl.set(el, origin);
|
|
16953
|
+
try {
|
|
16954
|
+
el.setAttribute(ORIGIN_ATTR, JSON.stringify(origin));
|
|
16955
|
+
} catch {
|
|
16956
|
+
}
|
|
16957
|
+
return origin;
|
|
16958
|
+
}
|
|
16959
|
+
function listStyleButtons(doc) {
|
|
16960
|
+
return Array.from(doc.querySelectorAll(CTA_BUTTON_SELECTOR)).filter((el) => {
|
|
16961
|
+
if (el.closest("[data-ohw-bridge], [data-ohw-bridge-root]")) return false;
|
|
16962
|
+
const rect = el.getBoundingClientRect();
|
|
16963
|
+
return rect.width > 0 && rect.height > 0;
|
|
16964
|
+
});
|
|
16965
|
+
}
|
|
16966
|
+
function generateTokensFromButtons(buttons) {
|
|
16967
|
+
const variants = generateButtonVariants(buttons.map(readVariantSample));
|
|
16968
|
+
const sizes = generateButtonSizes(buttons.map(readSizeSample));
|
|
16969
|
+
if (variants.status !== "ready" || sizes.status !== "ready") return { status: "unresolved" };
|
|
16970
|
+
return { status: "ready", tokens: { variants: variants.tokens, sizes: sizes.tokens } };
|
|
16971
|
+
}
|
|
16972
|
+
function tokensFromButton(el) {
|
|
16973
|
+
const origin = captureButtonOrigin(el);
|
|
16974
|
+
const sample = origin.variant;
|
|
16975
|
+
const variants = generateButtonVariants([sample]);
|
|
16976
|
+
const sizes = generateButtonSizes([origin.size]);
|
|
16977
|
+
const primary = chromeFrom(sample);
|
|
16978
|
+
return {
|
|
16979
|
+
variants: variants.status === "ready" ? variants.tokens : { primary, secondary: generatedSecondary(primary), ghost: generatedGhost(primary) },
|
|
16980
|
+
sizes: sizes.status === "ready" ? sizes.tokens : tokensFromSamples(REFERENCE_SIZES, 8, 8)
|
|
16981
|
+
};
|
|
16982
|
+
}
|
|
16983
|
+
function readStoredStyleTokens(content) {
|
|
16984
|
+
const variants = readVariantTokens(content);
|
|
16985
|
+
const sizes = readSizeTokens(content);
|
|
16986
|
+
if (!variants || !sizes) return null;
|
|
16987
|
+
return { variants, sizes };
|
|
16988
|
+
}
|
|
16989
|
+
function styleTokenNodes(tokens) {
|
|
16990
|
+
return [
|
|
16991
|
+
{ key: BUTTON_VARIANTS_KEY, text: JSON.stringify(tokens.variants) },
|
|
16992
|
+
{ key: BUTTON_SIZES_KEY, text: JSON.stringify(tokens.sizes) }
|
|
16993
|
+
];
|
|
16994
|
+
}
|
|
16995
|
+
function ensureButtonStyleTokens(doc, content) {
|
|
16996
|
+
const stored = readStoredStyleTokens(content);
|
|
16997
|
+
if (stored) return { tokens: stored, nodes: [] };
|
|
16998
|
+
const generated = generateTokensFromButtons(listStyleButtons(doc));
|
|
16999
|
+
if (generated.status !== "ready") return { tokens: null, nodes: [] };
|
|
17000
|
+
return { tokens: generated.tokens, nodes: styleTokenNodes(generated.tokens) };
|
|
17001
|
+
}
|
|
17002
|
+
function detectVariant(el, tokens) {
|
|
17003
|
+
const declared = declaredVariant(el.className || "");
|
|
17004
|
+
if (declared) return declared;
|
|
17005
|
+
const stamped = el.getAttribute("data-ohw-btn-variant");
|
|
17006
|
+
if (stamped && isButtonVariantId(stamped)) return stamped;
|
|
17007
|
+
const sample = readVariantSample(el);
|
|
17008
|
+
if (!tokens) return sampleSlot(sample);
|
|
17009
|
+
const key = fingerprint(sample);
|
|
17010
|
+
for (const id of BUTTON_VARIANT_IDS) {
|
|
17011
|
+
const chrome = tokens[id];
|
|
17012
|
+
const tokenKey = fingerprint({
|
|
17013
|
+
background: chrome.background,
|
|
17014
|
+
color: chrome.color,
|
|
17015
|
+
borderColor: chrome.borderColor,
|
|
17016
|
+
borderWidth: chrome.borderWidth,
|
|
17017
|
+
className: `btn btn--${id}`
|
|
17018
|
+
});
|
|
17019
|
+
if (tokenKey === key) return id;
|
|
17020
|
+
}
|
|
17021
|
+
return sampleSlot(sample);
|
|
17022
|
+
}
|
|
17023
|
+
function detectSize(el, tokens) {
|
|
17024
|
+
const stamped = el.getAttribute("data-ohw-btn-size");
|
|
17025
|
+
if (stamped && isButtonSizeId(stamped)) return stamped;
|
|
17026
|
+
const height = el.getBoundingClientRect().height;
|
|
17027
|
+
if (!tokens) return classifyHeight(height);
|
|
17028
|
+
let best = "m";
|
|
17029
|
+
let bestDelta = Number.POSITIVE_INFINITY;
|
|
17030
|
+
for (const id of BUTTON_SIZE_IDS) {
|
|
17031
|
+
const delta = Math.abs(tokens[id].height - height);
|
|
17032
|
+
if (delta < bestDelta) {
|
|
17033
|
+
best = id;
|
|
17034
|
+
bestDelta = delta;
|
|
17035
|
+
}
|
|
17036
|
+
}
|
|
17037
|
+
return best;
|
|
17038
|
+
}
|
|
17039
|
+
function assignmentFor(el, content, tokens) {
|
|
17040
|
+
const id = buttonId(el);
|
|
17041
|
+
const stored = id ? readAssignments(content)[id] : void 0;
|
|
17042
|
+
if (stored) return stored;
|
|
17043
|
+
return {
|
|
17044
|
+
variant: detectVariant(el, tokens?.variants ?? null),
|
|
17045
|
+
size: detectSize(el, tokens?.sizes ?? null)
|
|
17046
|
+
};
|
|
17047
|
+
}
|
|
17048
|
+
function labelElement(el) {
|
|
17049
|
+
return el.querySelector('[data-ohw-editable="text"], [data-ohw-editable="plain"]') ?? (el.matches('[data-ohw-editable="text"], [data-ohw-editable="plain"]') ? el : null);
|
|
17050
|
+
}
|
|
17051
|
+
var paintLockByEl = /* @__PURE__ */ new WeakMap();
|
|
17052
|
+
var paintObserverByEl = /* @__PURE__ */ new WeakMap();
|
|
17053
|
+
var paintingButton = false;
|
|
17054
|
+
function paintButtonChrome(el, assignment, tokens) {
|
|
17055
|
+
const origin = captureButtonOrigin(el);
|
|
17056
|
+
const chrome = tokens.variants[assignment.variant];
|
|
17057
|
+
const originSlot = classifyHeight(origin.size.height);
|
|
17058
|
+
const geometry = assignment.size === originSlot ? geometryFromSample({ ...origin.size, borderRadius: origin.size.borderRadius, gap: origin.size.gap }) : tokens.sizes[assignment.size];
|
|
17059
|
+
const { typography } = origin;
|
|
17060
|
+
el.setAttribute("data-ohw-btn-variant", assignment.variant);
|
|
17061
|
+
el.setAttribute("data-ohw-btn-size", assignment.size);
|
|
17062
|
+
el.style.transition = "none";
|
|
17063
|
+
el.style.boxSizing = "border-box";
|
|
17064
|
+
el.style.display = "inline-flex";
|
|
17065
|
+
el.style.alignItems = "center";
|
|
17066
|
+
el.style.justifyContent = "center";
|
|
17067
|
+
el.style.background = chrome.background;
|
|
17068
|
+
el.style.color = chrome.color;
|
|
17069
|
+
el.style.borderStyle = parseFloat(chrome.borderWidth) > 0 ? "solid" : "none";
|
|
17070
|
+
el.style.borderColor = chrome.borderColor;
|
|
17071
|
+
el.style.borderWidth = chrome.borderWidth;
|
|
17072
|
+
el.style.padding = `${geometry.paddingTop} ${geometry.paddingRight} ${geometry.paddingBottom} ${geometry.paddingLeft}`;
|
|
17073
|
+
el.style.fontSize = geometry.fontSize;
|
|
17074
|
+
el.style.borderRadius = px(origin.size.borderRadius);
|
|
17075
|
+
el.style.gap = geometry.gap;
|
|
17076
|
+
el.style.height = px(geometry.height);
|
|
17077
|
+
el.style.fontFamily = typography.fontFamily;
|
|
17078
|
+
el.style.fontWeight = typography.fontWeight;
|
|
17079
|
+
el.style.letterSpacing = typography.letterSpacing;
|
|
17080
|
+
el.style.textTransform = typography.textTransform;
|
|
17081
|
+
if (typography.textDecoration && typography.textDecoration !== "none") {
|
|
17082
|
+
el.style.textDecoration = typography.textDecoration;
|
|
17083
|
+
} else {
|
|
17084
|
+
el.style.textDecoration = "none";
|
|
17085
|
+
}
|
|
17086
|
+
const label = labelElement(el);
|
|
17087
|
+
if (label && label !== el) label.style.color = chrome.color;
|
|
17088
|
+
}
|
|
17089
|
+
function guardTemplateHover(el) {
|
|
17090
|
+
if (paintObserverByEl.has(el)) return;
|
|
17091
|
+
const observer = new MutationObserver(() => {
|
|
17092
|
+
if (paintingButton) return;
|
|
17093
|
+
const lock = paintLockByEl.get(el);
|
|
17094
|
+
if (!lock) return;
|
|
17095
|
+
paintingButton = true;
|
|
17096
|
+
paintButtonChrome(el, lock.assignment, lock.tokens);
|
|
17097
|
+
paintingButton = false;
|
|
17098
|
+
});
|
|
17099
|
+
observer.observe(el, { attributes: true, attributeFilter: ["style", "class"] });
|
|
17100
|
+
paintObserverByEl.set(el, observer);
|
|
17101
|
+
}
|
|
17102
|
+
function paintedTokensOf(el) {
|
|
17103
|
+
return paintLockByEl.get(el)?.tokens ?? null;
|
|
17104
|
+
}
|
|
17105
|
+
function applyButtonStyle(el, assignment, tokens) {
|
|
17106
|
+
paintLockByEl.set(el, { assignment, tokens });
|
|
17107
|
+
paintingButton = true;
|
|
17108
|
+
paintButtonChrome(el, assignment, tokens);
|
|
17109
|
+
paintingButton = false;
|
|
17110
|
+
guardTemplateHover(el);
|
|
17111
|
+
}
|
|
17112
|
+
function applyButtonStylesFromContent(doc, content) {
|
|
17113
|
+
const assignments = readAssignments(content);
|
|
17114
|
+
for (const [id, assignment] of Object.entries(assignments)) {
|
|
17115
|
+
const el = doc.querySelector(`[data-ohw-href-key="${CSS.escape(id)}"]`);
|
|
17116
|
+
if (!el) continue;
|
|
17117
|
+
applyButtonStyle(el, assignment, tokensFromButton(el));
|
|
17118
|
+
}
|
|
17119
|
+
}
|
|
17120
|
+
function withAssignment(content, id, assignment) {
|
|
17121
|
+
return { ...readAssignments(content), [id]: assignment };
|
|
17122
|
+
}
|
|
17123
|
+
|
|
17124
|
+
// src/ui/button-style-panel.tsx
|
|
17125
|
+
var import_jsx_runtime31 = require("react/jsx-runtime");
|
|
17126
|
+
var SIZE_LABEL = { s: "S", m: "M", l: "L" };
|
|
17127
|
+
function ButtonStylePanel({
|
|
17128
|
+
variants,
|
|
17129
|
+
sizes,
|
|
17130
|
+
variant,
|
|
17131
|
+
size,
|
|
17132
|
+
onVariant,
|
|
17133
|
+
onSize,
|
|
17134
|
+
previewLabel = "Book Now",
|
|
17135
|
+
slotBackground = "var(--brand-background, var(--ohw-brand-light, var(--color-light, #ffffff)))"
|
|
17136
|
+
}) {
|
|
17137
|
+
const preview = scaleGeometry(sizes.m, 0.75);
|
|
17138
|
+
const label = previewLabel.trim() || "Book Now";
|
|
17139
|
+
return /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)("div", { className: "flex w-full flex-col gap-5", children: [
|
|
17140
|
+
/* @__PURE__ */ (0, import_jsx_runtime31.jsxs)("section", { className: "flex w-full flex-col gap-2.5", children: [
|
|
17141
|
+
/* @__PURE__ */ (0, import_jsx_runtime31.jsx)("h3", { className: "text-xs font-semibold uppercase leading-4 tracking-[0.6px] text-stone-500 font-sans", children: "Variants" }),
|
|
17142
|
+
/* @__PURE__ */ (0, import_jsx_runtime31.jsx)("div", { className: "flex w-full flex-col gap-2.5", children: BUTTON_VARIANT_IDS.map((id) => {
|
|
17143
|
+
const chrome = variants[id];
|
|
17144
|
+
const selected = id === variant;
|
|
17145
|
+
const hasBorder = parseFloat(chrome.borderWidth) > 0;
|
|
17146
|
+
const cardSlot = previewSlotForChrome(chrome, slotBackground);
|
|
17147
|
+
return /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)(
|
|
17148
|
+
"button",
|
|
17149
|
+
{
|
|
17150
|
+
type: "button",
|
|
17151
|
+
"aria-pressed": selected,
|
|
17152
|
+
"aria-label": id,
|
|
17153
|
+
onMouseDown: (e) => {
|
|
17154
|
+
e.preventDefault();
|
|
17155
|
+
e.stopPropagation();
|
|
17156
|
+
},
|
|
17157
|
+
onClick: () => onVariant(id),
|
|
17158
|
+
className: cn(
|
|
17159
|
+
"relative w-full overflow-hidden rounded-xl border-solid text-left",
|
|
17160
|
+
selected ? "border-2 border-primary" : "border border-border"
|
|
17161
|
+
),
|
|
17162
|
+
children: [
|
|
17163
|
+
/* @__PURE__ */ (0, import_jsx_runtime31.jsx)(
|
|
17164
|
+
"div",
|
|
17165
|
+
{
|
|
17166
|
+
className: "flex w-full items-center justify-center py-4",
|
|
17167
|
+
style: { background: cardSlot },
|
|
17168
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(
|
|
17169
|
+
"span",
|
|
17170
|
+
{
|
|
17171
|
+
className: "inline-flex items-center justify-center whitespace-nowrap font-semibold uppercase leading-none",
|
|
17172
|
+
style: {
|
|
17173
|
+
background: chrome.background,
|
|
17174
|
+
color: chrome.color,
|
|
17175
|
+
borderColor: chrome.borderColor,
|
|
17176
|
+
borderWidth: hasBorder ? chrome.borderWidth : "0px",
|
|
17177
|
+
borderStyle: hasBorder ? "solid" : "none",
|
|
17178
|
+
padding: `${preview.paddingTop} ${preview.paddingRight} ${preview.paddingBottom} ${preview.paddingLeft}`,
|
|
17179
|
+
fontSize: preview.fontSize,
|
|
17180
|
+
borderRadius: preview.borderRadius,
|
|
17181
|
+
height: preview.height,
|
|
17182
|
+
boxSizing: "border-box",
|
|
17183
|
+
letterSpacing: "0.12em"
|
|
17184
|
+
},
|
|
17185
|
+
children: label
|
|
17186
|
+
}
|
|
17187
|
+
)
|
|
17188
|
+
}
|
|
17189
|
+
),
|
|
17190
|
+
selected ? /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(
|
|
17191
|
+
"span",
|
|
17192
|
+
{
|
|
17193
|
+
className: "absolute right-0.5 top-0.5 flex size-5 items-center justify-center rounded-full bg-primary text-primary-foreground",
|
|
17194
|
+
"aria-hidden": true,
|
|
17195
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(import_lucide_react17.Check, { className: "size-3", strokeWidth: 3 })
|
|
17196
|
+
}
|
|
17197
|
+
) : null
|
|
17198
|
+
]
|
|
17199
|
+
},
|
|
17200
|
+
id
|
|
17201
|
+
);
|
|
17202
|
+
}) })
|
|
17203
|
+
] }),
|
|
17204
|
+
/* @__PURE__ */ (0, import_jsx_runtime31.jsxs)("section", { className: "flex w-full flex-col gap-2.5", children: [
|
|
17205
|
+
/* @__PURE__ */ (0, import_jsx_runtime31.jsx)("h3", { className: "text-xs font-semibold uppercase leading-4 tracking-[0.6px] text-stone-500 font-sans", children: "Size" }),
|
|
17206
|
+
/* @__PURE__ */ (0, import_jsx_runtime31.jsx)(
|
|
17207
|
+
"div",
|
|
17208
|
+
{
|
|
17209
|
+
className: "flex w-full items-start rounded-lg bg-stone-100 p-1",
|
|
17210
|
+
role: "radiogroup",
|
|
17211
|
+
"aria-label": "Size",
|
|
17212
|
+
children: BUTTON_SIZE_IDS.map((id) => {
|
|
17213
|
+
const selected = id === size;
|
|
17214
|
+
return /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(
|
|
17215
|
+
"button",
|
|
17216
|
+
{
|
|
17217
|
+
type: "button",
|
|
17218
|
+
role: "radio",
|
|
17219
|
+
"aria-checked": selected,
|
|
17220
|
+
onMouseDown: (e) => {
|
|
17221
|
+
e.preventDefault();
|
|
17222
|
+
e.stopPropagation();
|
|
17223
|
+
},
|
|
17224
|
+
onClick: () => onSize(id),
|
|
17225
|
+
className: cn(
|
|
17226
|
+
"flex min-w-14 flex-1 items-center justify-center rounded-md px-3 py-1.5 text-sm font-medium leading-5",
|
|
17227
|
+
selected ? "bg-white text-stone-950 shadow-sm" : "bg-transparent text-stone-500"
|
|
17228
|
+
),
|
|
17229
|
+
children: SIZE_LABEL[id]
|
|
17230
|
+
},
|
|
17231
|
+
id
|
|
17232
|
+
);
|
|
17233
|
+
})
|
|
17234
|
+
}
|
|
17235
|
+
)
|
|
17236
|
+
] })
|
|
17237
|
+
] });
|
|
17238
|
+
}
|
|
17239
|
+
|
|
17240
|
+
// src/lib/button-collections.ts
|
|
17241
|
+
var BUTTON_COLLECTIONS_KEY = "__ohw_button_collections";
|
|
17242
|
+
var BUTTON_SNAPSHOTS_KEY = "__ohw_button_snapshots";
|
|
17243
|
+
var BUTTON_HIDDEN_KEY = "__ohw_button_hidden";
|
|
17244
|
+
var COLLECTION_ATTR = "data-ohw-button-collection";
|
|
17245
|
+
function parseJson2(raw) {
|
|
17246
|
+
if (!raw) return null;
|
|
17247
|
+
try {
|
|
17248
|
+
return JSON.parse(raw);
|
|
17249
|
+
} catch {
|
|
17250
|
+
return null;
|
|
17251
|
+
}
|
|
17252
|
+
}
|
|
17253
|
+
function readCollections(content) {
|
|
17254
|
+
const parsed = parseJson2(content[BUTTON_COLLECTIONS_KEY]);
|
|
17255
|
+
if (!parsed || typeof parsed !== "object") return {};
|
|
17256
|
+
const next = {};
|
|
17257
|
+
for (const [id, value] of Object.entries(parsed)) {
|
|
17258
|
+
if (!value || !Array.isArray(value.members)) continue;
|
|
17259
|
+
next[id] = {
|
|
17260
|
+
id,
|
|
17261
|
+
members: value.members.filter((member) => typeof member === "string" && member),
|
|
17262
|
+
gap: typeof value.gap === "string" ? value.gap : "12px"
|
|
17263
|
+
};
|
|
17264
|
+
}
|
|
17265
|
+
return next;
|
|
17266
|
+
}
|
|
17267
|
+
function readSnapshots(content) {
|
|
17268
|
+
const parsed = parseJson2(content[BUTTON_SNAPSHOTS_KEY]);
|
|
17269
|
+
if (!parsed || typeof parsed !== "object") return {};
|
|
17270
|
+
const next = {};
|
|
17271
|
+
for (const [id, value] of Object.entries(parsed)) {
|
|
17272
|
+
if (!value || typeof value.html !== "string") continue;
|
|
17273
|
+
next[id] = value;
|
|
17274
|
+
}
|
|
17275
|
+
return next;
|
|
17276
|
+
}
|
|
17277
|
+
function readHiddenButtons(content) {
|
|
17278
|
+
const parsed = parseJson2(content[BUTTON_HIDDEN_KEY]);
|
|
17279
|
+
if (!Array.isArray(parsed)) return [];
|
|
17280
|
+
return parsed.filter((id) => typeof id === "string" && id);
|
|
17281
|
+
}
|
|
17282
|
+
function buttonCollectionOf(el) {
|
|
17283
|
+
return el?.closest(`[${COLLECTION_ATTR}]`) ?? null;
|
|
17284
|
+
}
|
|
17285
|
+
function isNavbarCta(el) {
|
|
17286
|
+
return el.getAttribute("data-ohw-role") === "navbar-button" || Boolean(el.closest('[data-ohw-role="navbar-button"]'));
|
|
17287
|
+
}
|
|
17288
|
+
function navbarScope(el) {
|
|
17289
|
+
return el.closest("nav, [data-ohw-nav-container], [data-ohw-nav-drawer]") ?? el.ownerDocument;
|
|
17290
|
+
}
|
|
17291
|
+
function isLastNavbarButton(el) {
|
|
17292
|
+
if (!isNavbarCta(el)) return false;
|
|
17293
|
+
const buttons = Array.from(navbarScope(el).querySelectorAll(CTA_BUTTON_SELECTOR)).filter(
|
|
17294
|
+
(button) => isNavbarCta(button) && buttonId(button)
|
|
17295
|
+
);
|
|
17296
|
+
return buttons.length <= 1;
|
|
17297
|
+
}
|
|
17298
|
+
function canDeleteButton(el) {
|
|
17299
|
+
return !isLastNavbarButton(el);
|
|
17300
|
+
}
|
|
17301
|
+
function canDuplicateButton(el) {
|
|
17302
|
+
return isNavbarCta(el);
|
|
17303
|
+
}
|
|
17304
|
+
function labelElement2(el) {
|
|
17305
|
+
return el.querySelector('[data-ohw-editable="text"], [data-ohw-editable="plain"]') ?? el.querySelector("[data-ohw-key]");
|
|
17306
|
+
}
|
|
17307
|
+
function buttonLabel(el) {
|
|
17308
|
+
return (labelElement2(el)?.textContent ?? el.textContent ?? "").trim();
|
|
17309
|
+
}
|
|
17310
|
+
function buttonHref(el) {
|
|
17311
|
+
return el.getAttribute("href") ?? "";
|
|
17312
|
+
}
|
|
17313
|
+
function hrefKeyBase(hrefKey) {
|
|
17314
|
+
return hrefKey.replace(/-href$/, "").replace(/-copy-\d+$/, "");
|
|
17315
|
+
}
|
|
17316
|
+
function labelKeyForHrefKey(hrefKey) {
|
|
17317
|
+
return `${hrefKey.replace(/-href$/, "")}-label`;
|
|
17318
|
+
}
|
|
17319
|
+
function cleanClone(el) {
|
|
17320
|
+
const copy = el.cloneNode(true);
|
|
17321
|
+
copy.querySelectorAll("[data-ohw-selected], [data-ohw-hovered], [data-ohw-editing]").forEach((node) => {
|
|
17322
|
+
node.removeAttribute("data-ohw-selected");
|
|
17323
|
+
node.removeAttribute("data-ohw-hovered");
|
|
17324
|
+
node.removeAttribute("data-ohw-editing");
|
|
17325
|
+
node.removeAttribute("contenteditable");
|
|
17326
|
+
});
|
|
17327
|
+
copy.removeAttribute("data-ohw-selected");
|
|
17328
|
+
copy.removeAttribute("data-ohw-hovered");
|
|
17329
|
+
copy.removeAttribute("data-ohw-editing");
|
|
17330
|
+
copy.removeAttribute("contenteditable");
|
|
17331
|
+
copy.removeAttribute("data-ohw-drag-disabled");
|
|
17332
|
+
return copy;
|
|
17333
|
+
}
|
|
17334
|
+
function nextCopyId(sourceId, content, doc) {
|
|
17335
|
+
const used = /* @__PURE__ */ new Set([
|
|
17336
|
+
...Object.keys(readSnapshots(content)),
|
|
17337
|
+
...Object.keys(readAssignments(content)),
|
|
17338
|
+
...Array.from(doc.querySelectorAll("[data-ohw-href-key]")).map(
|
|
17339
|
+
(el) => el.getAttribute("data-ohw-href-key") ?? ""
|
|
17340
|
+
)
|
|
17341
|
+
]);
|
|
17342
|
+
const base = hrefKeyBase(sourceId);
|
|
17343
|
+
let n = 2;
|
|
17344
|
+
while (used.has(`${base}-copy-${n}-href`)) n += 1;
|
|
17345
|
+
return `${base}-copy-${n}-href`;
|
|
17346
|
+
}
|
|
17347
|
+
function nextCollectionId(content, doc) {
|
|
17348
|
+
const used = /* @__PURE__ */ new Set([
|
|
17349
|
+
...Object.keys(readCollections(content)),
|
|
17350
|
+
...Array.from(doc.querySelectorAll(`[${COLLECTION_ATTR}]`)).map(
|
|
17351
|
+
(el) => el.getAttribute(COLLECTION_ATTR) ?? ""
|
|
17352
|
+
)
|
|
17353
|
+
]);
|
|
17354
|
+
let n = 1;
|
|
17355
|
+
while (used.has(`bc-${n}`)) n += 1;
|
|
17356
|
+
return `bc-${n}`;
|
|
17357
|
+
}
|
|
17358
|
+
var COLLECTION_GAP_MAX_PX = 12;
|
|
17359
|
+
var COLLECTION_GAP_DEFAULT = "12px";
|
|
17360
|
+
function usableGap(value) {
|
|
17361
|
+
if (!value || value === "normal") return null;
|
|
17362
|
+
const n = parseFloat(value);
|
|
17363
|
+
if (!Number.isFinite(n) || n <= 0) return null;
|
|
17364
|
+
if (n > COLLECTION_GAP_MAX_PX) return COLLECTION_GAP_DEFAULT;
|
|
17365
|
+
return `${Math.round(n * 100) / 100}px`;
|
|
17366
|
+
}
|
|
17367
|
+
function collectionGap(el, tokens) {
|
|
17368
|
+
const fromCollection = usableGap(buttonCollectionOf(el)?.style.gap);
|
|
17369
|
+
if (fromCollection) return fromCollection;
|
|
17370
|
+
const parent = el.parentElement;
|
|
17371
|
+
if (parent) {
|
|
17372
|
+
const style = getComputedStyle(parent);
|
|
17373
|
+
const fromParent = usableGap(style.columnGap) ?? usableGap(style.gap);
|
|
17374
|
+
if (fromParent) return fromParent;
|
|
17375
|
+
}
|
|
17376
|
+
const fromTokens = usableGap(tokens?.sizes.m.gap);
|
|
17377
|
+
if (fromTokens) return fromTokens;
|
|
17378
|
+
return COLLECTION_GAP_DEFAULT;
|
|
17379
|
+
}
|
|
17380
|
+
function styleCollection(collection, gap) {
|
|
17381
|
+
collection.style.display = "inline-flex";
|
|
17382
|
+
collection.style.alignItems = "center";
|
|
17383
|
+
collection.style.flexWrap = "wrap";
|
|
17384
|
+
collection.style.gap = gap;
|
|
17385
|
+
collection.style.maxWidth = "100%";
|
|
17386
|
+
}
|
|
17387
|
+
function createCollection(doc, id, gap) {
|
|
17388
|
+
const collection = doc.createElement("div");
|
|
17389
|
+
collection.setAttribute(COLLECTION_ATTR, id);
|
|
17390
|
+
styleCollection(collection, gap);
|
|
17391
|
+
return collection;
|
|
17392
|
+
}
|
|
17393
|
+
function setButtonDragAttr(el) {
|
|
17394
|
+
if (isNavbarCta(el) && buttonCollectionOf(el)) el.removeAttribute("data-ohw-drag-disabled");
|
|
17395
|
+
else el.setAttribute("data-ohw-drag-disabled", "true");
|
|
17396
|
+
}
|
|
17397
|
+
function rekeyCopy(copy, id) {
|
|
17398
|
+
copy.setAttribute("data-ohw-href-key", id);
|
|
17399
|
+
const label = labelElement2(copy);
|
|
17400
|
+
const labelKey = labelKeyForHrefKey(id);
|
|
17401
|
+
if (label) label.setAttribute("data-ohw-key", labelKey);
|
|
17402
|
+
setButtonDragAttr(copy);
|
|
17403
|
+
return { labelKey };
|
|
17404
|
+
}
|
|
17405
|
+
function stampVariantClass(el, variant) {
|
|
17406
|
+
const raw = typeof el.className === "string" ? el.className : el.getAttribute("class") || "";
|
|
17407
|
+
const without = raw.replace(/\bbtn--(?:primary|secondary|ghost)\b/g, "").replace(/\s+/g, " ").trim();
|
|
17408
|
+
el.className = without ? `${without} btn--${variant}` : `btn btn--${variant}`;
|
|
17409
|
+
}
|
|
17410
|
+
function snapshotOf(el) {
|
|
17411
|
+
const id = buttonId(el) ?? "";
|
|
17412
|
+
const label = labelElement2(el);
|
|
17413
|
+
return {
|
|
17414
|
+
id,
|
|
17415
|
+
href: buttonHref(el),
|
|
17416
|
+
label: buttonLabel(el),
|
|
17417
|
+
labelKey: label?.getAttribute("data-ohw-key") ?? labelKeyForHrefKey(id),
|
|
17418
|
+
html: cleanClone(el).outerHTML
|
|
17419
|
+
};
|
|
17420
|
+
}
|
|
17421
|
+
function htmlToElement(doc, html) {
|
|
17422
|
+
const wrap = doc.createElement("div");
|
|
17423
|
+
wrap.innerHTML = html;
|
|
17424
|
+
const el = wrap.firstElementChild;
|
|
17425
|
+
return el instanceof HTMLElement ? el : null;
|
|
17426
|
+
}
|
|
17427
|
+
function findButton(doc, id) {
|
|
17428
|
+
return doc.querySelector(`[data-ohw-href-key="${CSS.escape(id)}"]`);
|
|
17429
|
+
}
|
|
17430
|
+
function duplicateButton(source, content) {
|
|
17431
|
+
if (!canDuplicateButton(source)) return null;
|
|
17432
|
+
const sourceId = buttonId(source);
|
|
17433
|
+
if (!sourceId) return null;
|
|
17434
|
+
const doc = source.ownerDocument;
|
|
17435
|
+
const tokens = tokensFromButton(source);
|
|
17436
|
+
const copyId = nextCopyId(sourceId, content, doc);
|
|
17437
|
+
const copy = cleanClone(source);
|
|
17438
|
+
const { labelKey } = rekeyCopy(copy, copyId);
|
|
17439
|
+
const href = buttonHref(source);
|
|
17440
|
+
const label = buttonLabel(source);
|
|
17441
|
+
if (href) copy.setAttribute("href", href);
|
|
17442
|
+
const sourceAssignment = readAssignments(content)[sourceId] ?? assignmentFor(source, content, tokens);
|
|
17443
|
+
const copyAssignment = { ...sourceAssignment };
|
|
17444
|
+
stampVariantClass(copy, copyAssignment.variant);
|
|
17445
|
+
applyButtonStyle(copy, copyAssignment, paintedTokensOf(source) ?? tokens);
|
|
17446
|
+
const copyLabelEl = labelElement2(copy);
|
|
17447
|
+
if (copyLabelEl) copyLabelEl.textContent = label;
|
|
17448
|
+
let collection = buttonCollectionOf(source);
|
|
17449
|
+
const collections = readCollections(content);
|
|
17450
|
+
let collectionId = collection?.getAttribute(COLLECTION_ATTR) ?? "";
|
|
17451
|
+
let members = collectionId && collections[collectionId] ? [...collections[collectionId].members] : [];
|
|
17452
|
+
const gap = collectionGap(source, tokens);
|
|
17453
|
+
if (!collection) {
|
|
17454
|
+
collectionId = nextCollectionId(content, doc);
|
|
17455
|
+
collection = createCollection(doc, collectionId, gap);
|
|
17456
|
+
source.parentElement?.insertBefore(collection, source);
|
|
17457
|
+
collection.append(source, copy);
|
|
17458
|
+
setButtonDragAttr(source);
|
|
17459
|
+
setButtonDragAttr(copy);
|
|
17460
|
+
members = [sourceId, copyId];
|
|
17461
|
+
} else {
|
|
17462
|
+
styleCollection(collection, gap);
|
|
17463
|
+
source.after(copy);
|
|
17464
|
+
setButtonDragAttr(copy);
|
|
17465
|
+
if (!members.includes(sourceId)) members = listCollectionMembers(collection);
|
|
17466
|
+
const at = members.indexOf(sourceId);
|
|
17467
|
+
members.splice(at >= 0 ? at + 1 : members.length, 0, copyId);
|
|
17468
|
+
}
|
|
17469
|
+
const sourceLabelKey = labelElement2(source)?.getAttribute("data-ohw-key");
|
|
17470
|
+
const snapshots = {
|
|
17471
|
+
...readSnapshots(content),
|
|
17472
|
+
[sourceId]: snapshotOf(source),
|
|
17473
|
+
[copyId]: snapshotOf(copy)
|
|
17474
|
+
};
|
|
17475
|
+
const nextCollections = {
|
|
17476
|
+
...collections,
|
|
17477
|
+
[collectionId]: { id: collectionId, members, gap }
|
|
17478
|
+
};
|
|
17479
|
+
const assignments = withAssignment(content, copyId, copyAssignment);
|
|
17480
|
+
const nextContent = {
|
|
17481
|
+
...content,
|
|
17482
|
+
[copyId]: href,
|
|
17483
|
+
[labelKey]: label,
|
|
17484
|
+
[BUTTON_COLLECTIONS_KEY]: JSON.stringify(nextCollections),
|
|
17485
|
+
[BUTTON_SNAPSHOTS_KEY]: JSON.stringify(snapshots),
|
|
17486
|
+
[BUTTON_ASSIGNMENTS_KEY]: JSON.stringify(assignments)
|
|
17487
|
+
};
|
|
17488
|
+
if (sourceLabelKey && nextContent[sourceLabelKey] === void 0) {
|
|
17489
|
+
nextContent[sourceLabelKey] = label;
|
|
17490
|
+
}
|
|
17491
|
+
const nodeKeys = [
|
|
17492
|
+
copyId,
|
|
17493
|
+
labelKey,
|
|
17494
|
+
BUTTON_COLLECTIONS_KEY,
|
|
17495
|
+
BUTTON_SNAPSHOTS_KEY,
|
|
17496
|
+
BUTTON_ASSIGNMENTS_KEY
|
|
17497
|
+
];
|
|
17498
|
+
if (sourceLabelKey) nodeKeys.push(sourceLabelKey);
|
|
17499
|
+
return {
|
|
17500
|
+
copy,
|
|
17501
|
+
content: nextContent,
|
|
17502
|
+
nodes: contentNodes(nextContent, nodeKeys)
|
|
17503
|
+
};
|
|
17504
|
+
}
|
|
17505
|
+
function listCollectionMembers(collection) {
|
|
17506
|
+
return Array.from(collection.querySelectorAll(CTA_BUTTON_SELECTOR)).map((el) => buttonId(el)).filter((id) => Boolean(id));
|
|
17507
|
+
}
|
|
17508
|
+
function contentNodes(content, keys) {
|
|
17509
|
+
return keys.filter((key) => content[key] !== void 0).map((key) => ({ key, text: content[key] }));
|
|
17510
|
+
}
|
|
17511
|
+
function deleteButton(source, content) {
|
|
17512
|
+
if (!canDeleteButton(source)) return null;
|
|
17513
|
+
const id = buttonId(source);
|
|
17514
|
+
if (!id) return null;
|
|
17515
|
+
const parent = source.parentElement;
|
|
17516
|
+
const nextSibling = source.nextSibling;
|
|
17517
|
+
const removed = source;
|
|
17518
|
+
const collection = buttonCollectionOf(source);
|
|
17519
|
+
const collectionId = collection?.getAttribute(COLLECTION_ATTR) ?? "";
|
|
17520
|
+
const previousCollections = readCollections(content);
|
|
17521
|
+
const previousHidden = readHiddenButtons(content);
|
|
17522
|
+
const snapshots = { ...readSnapshots(content) };
|
|
17523
|
+
const assignments = { ...readAssignments(content) };
|
|
17524
|
+
delete assignments[id];
|
|
17525
|
+
const remainingBeforeUnwrap = collection ? listCollectionMembers(collection).filter((member) => member !== id) : [];
|
|
17526
|
+
removed.remove();
|
|
17527
|
+
let nextCollections = { ...previousCollections };
|
|
17528
|
+
let unwrapped = null;
|
|
17529
|
+
if (collection && collectionId) {
|
|
17530
|
+
const members = listCollectionMembers(collection);
|
|
17531
|
+
if (members.length <= 1) {
|
|
17532
|
+
unwrapped = collection;
|
|
17533
|
+
unwrapCollection(collection);
|
|
17534
|
+
delete nextCollections[collectionId];
|
|
17535
|
+
} else {
|
|
17536
|
+
nextCollections[collectionId] = {
|
|
17537
|
+
id: collectionId,
|
|
17538
|
+
members,
|
|
17539
|
+
gap: collection.style.gap || previousCollections[collectionId]?.gap || "12px"
|
|
17540
|
+
};
|
|
17541
|
+
}
|
|
17542
|
+
}
|
|
17543
|
+
const hidden = previousHidden.includes(id) ? previousHidden : [...previousHidden, id];
|
|
17544
|
+
const nextContent = {
|
|
17545
|
+
...content,
|
|
17546
|
+
[id]: "",
|
|
17547
|
+
[BUTTON_COLLECTIONS_KEY]: JSON.stringify(nextCollections),
|
|
17548
|
+
[BUTTON_HIDDEN_KEY]: JSON.stringify(hidden),
|
|
17549
|
+
[BUTTON_SNAPSHOTS_KEY]: JSON.stringify(snapshots),
|
|
17550
|
+
[BUTTON_ASSIGNMENTS_KEY]: JSON.stringify(assignments)
|
|
17551
|
+
};
|
|
17552
|
+
return {
|
|
17553
|
+
content: nextContent,
|
|
17554
|
+
nodes: contentNodes(nextContent, [id, BUTTON_COLLECTIONS_KEY, BUTTON_HIDDEN_KEY, BUTTON_SNAPSHOTS_KEY, BUTTON_ASSIGNMENTS_KEY]),
|
|
17555
|
+
undo: () => {
|
|
17556
|
+
if (unwrapped && remainingBeforeUnwrap.length === 1) {
|
|
17557
|
+
const remaining = findButton(removed.ownerDocument, remainingBeforeUnwrap[0]);
|
|
17558
|
+
const host = remaining?.parentElement;
|
|
17559
|
+
if (remaining && host) {
|
|
17560
|
+
const restoredCollection = createCollection(
|
|
17561
|
+
removed.ownerDocument,
|
|
17562
|
+
collectionId,
|
|
17563
|
+
previousCollections[collectionId]?.gap || "12px"
|
|
17564
|
+
);
|
|
17565
|
+
host.insertBefore(restoredCollection, remaining);
|
|
17566
|
+
restoredCollection.append(remaining, removed);
|
|
17567
|
+
return;
|
|
17568
|
+
}
|
|
17569
|
+
}
|
|
17570
|
+
if (nextSibling && nextSibling.parentNode === parent) parent?.insertBefore(removed, nextSibling);
|
|
17571
|
+
else parent?.appendChild(removed);
|
|
17572
|
+
}
|
|
17573
|
+
};
|
|
17574
|
+
}
|
|
17575
|
+
function unwrapCollection(collection) {
|
|
17576
|
+
const parent = collection.parentElement;
|
|
17577
|
+
if (!parent) return;
|
|
17578
|
+
while (collection.firstChild) parent.insertBefore(collection.firstChild, collection);
|
|
17579
|
+
collection.remove();
|
|
17580
|
+
}
|
|
17581
|
+
function reorderButtonInCollection(button, clientX) {
|
|
17582
|
+
const collection = buttonCollectionOf(button);
|
|
17583
|
+
const id = buttonId(button);
|
|
17584
|
+
if (!collection || !id) return null;
|
|
17585
|
+
const siblings = Array.from(collection.querySelectorAll(CTA_BUTTON_SELECTOR)).filter((el) => el !== button);
|
|
17586
|
+
let placed = false;
|
|
17587
|
+
for (const sibling of siblings) {
|
|
17588
|
+
const rect = sibling.getBoundingClientRect();
|
|
17589
|
+
if (clientX < rect.left + rect.width / 2) {
|
|
17590
|
+
sibling.before(button);
|
|
17591
|
+
placed = true;
|
|
17592
|
+
break;
|
|
17593
|
+
}
|
|
17594
|
+
}
|
|
17595
|
+
if (!placed) collection.append(button);
|
|
17596
|
+
return listCollectionMembers(collection);
|
|
17597
|
+
}
|
|
17598
|
+
function listVisibleCollectionButtons(collection) {
|
|
17599
|
+
return Array.from(collection.querySelectorAll(CTA_BUTTON_SELECTOR)).filter((el) => {
|
|
17600
|
+
if (!buttonId(el)) return false;
|
|
17601
|
+
return el.getClientRects().length > 0;
|
|
17602
|
+
});
|
|
17603
|
+
}
|
|
17604
|
+
function isVerticalButtonLayout(items, collection) {
|
|
17605
|
+
if (items.length >= 2) {
|
|
17606
|
+
const a = items[0].getBoundingClientRect();
|
|
17607
|
+
const b = items[1].getBoundingClientRect();
|
|
17608
|
+
return b.top - a.bottom > b.left - a.right;
|
|
17609
|
+
}
|
|
17610
|
+
const style = window.getComputedStyle(collection);
|
|
17611
|
+
return style.flexDirection === "column" || style.flexDirection === "column-reverse";
|
|
17612
|
+
}
|
|
17613
|
+
function buildButtonCollectionDropSlots(collection) {
|
|
17614
|
+
const items = listVisibleCollectionButtons(collection);
|
|
17615
|
+
const barThickness = 3;
|
|
17616
|
+
const slots = [];
|
|
17617
|
+
if (items.length === 0) {
|
|
17618
|
+
const rect = collection.getBoundingClientRect();
|
|
17619
|
+
slots.push({
|
|
17620
|
+
insertIndex: 0,
|
|
17621
|
+
left: rect.left + rect.width / 2 - barThickness / 2,
|
|
17622
|
+
top: rect.top,
|
|
17623
|
+
width: barThickness,
|
|
17624
|
+
height: Math.max(rect.height, 24),
|
|
17625
|
+
direction: "vertical"
|
|
17626
|
+
});
|
|
17627
|
+
return slots;
|
|
17628
|
+
}
|
|
17629
|
+
if (isVerticalButtonLayout(items, collection)) {
|
|
17630
|
+
const edgeGap2 = items.length >= 2 ? Math.max(0, items[1].getBoundingClientRect().top - items[0].getBoundingClientRect().bottom) : 16;
|
|
17631
|
+
for (let i = 0; i <= items.length; i++) {
|
|
17632
|
+
let top;
|
|
17633
|
+
let left;
|
|
17634
|
+
let width;
|
|
17635
|
+
if (i === 0) {
|
|
17636
|
+
const first = items[0].getBoundingClientRect();
|
|
17637
|
+
top = first.top - edgeGap2 / 2 - barThickness / 2;
|
|
17638
|
+
left = first.left;
|
|
17639
|
+
width = first.width;
|
|
17640
|
+
} else if (i === items.length) {
|
|
17641
|
+
const last = items[items.length - 1].getBoundingClientRect();
|
|
17642
|
+
const lastGap = items.length >= 2 ? Math.max(0, last.top - items[items.length - 2].getBoundingClientRect().bottom) : edgeGap2;
|
|
17643
|
+
top = last.bottom + lastGap / 2 - barThickness / 2;
|
|
17644
|
+
left = last.left;
|
|
17645
|
+
width = last.width;
|
|
17646
|
+
} else {
|
|
17647
|
+
const prev = items[i - 1].getBoundingClientRect();
|
|
17648
|
+
const next = items[i].getBoundingClientRect();
|
|
17649
|
+
top = (prev.bottom + next.top) / 2 - barThickness / 2;
|
|
17650
|
+
left = Math.min(prev.left, next.left);
|
|
17651
|
+
width = Math.max(prev.right, next.right) - left;
|
|
17652
|
+
}
|
|
17653
|
+
slots.push({
|
|
17654
|
+
insertIndex: i,
|
|
17655
|
+
left,
|
|
17656
|
+
top,
|
|
17657
|
+
width: Math.max(width, 40),
|
|
17658
|
+
height: barThickness,
|
|
17659
|
+
direction: "horizontal"
|
|
17660
|
+
});
|
|
17661
|
+
}
|
|
17662
|
+
return slots;
|
|
17663
|
+
}
|
|
17664
|
+
const edgeGap = items.length >= 2 ? Math.max(0, items[1].getBoundingClientRect().left - items[0].getBoundingClientRect().right) : 12;
|
|
17665
|
+
for (let i = 0; i <= items.length; i++) {
|
|
17666
|
+
let left;
|
|
17667
|
+
let top;
|
|
17668
|
+
let height;
|
|
17669
|
+
if (i === 0) {
|
|
17670
|
+
const first = items[0].getBoundingClientRect();
|
|
17671
|
+
left = first.left - edgeGap / 2 - barThickness / 2;
|
|
17672
|
+
top = first.top;
|
|
17673
|
+
height = first.height;
|
|
17674
|
+
} else if (i === items.length) {
|
|
17675
|
+
const last = items[items.length - 1].getBoundingClientRect();
|
|
17676
|
+
const lastGap = items.length >= 2 ? Math.max(0, last.left - items[items.length - 2].getBoundingClientRect().right) : edgeGap;
|
|
17677
|
+
left = last.right + lastGap / 2 - barThickness / 2;
|
|
17678
|
+
top = last.top;
|
|
17679
|
+
height = last.height;
|
|
17680
|
+
} else {
|
|
17681
|
+
const prev = items[i - 1].getBoundingClientRect();
|
|
17682
|
+
const next = items[i].getBoundingClientRect();
|
|
17683
|
+
left = (prev.right + next.left) / 2 - barThickness / 2;
|
|
17684
|
+
top = Math.min(prev.top, next.top);
|
|
17685
|
+
height = Math.max(prev.bottom, next.bottom) - top;
|
|
17686
|
+
}
|
|
17687
|
+
slots.push({
|
|
17688
|
+
insertIndex: i,
|
|
17689
|
+
left,
|
|
17690
|
+
top,
|
|
17691
|
+
width: barThickness,
|
|
17692
|
+
height: Math.max(height, 24),
|
|
17693
|
+
direction: "vertical"
|
|
17694
|
+
});
|
|
17695
|
+
}
|
|
17696
|
+
return slots;
|
|
17697
|
+
}
|
|
17698
|
+
function hitTestButtonCollectionDropSlot(collection, clientX, clientY) {
|
|
17699
|
+
const slots = buildButtonCollectionDropSlots(collection);
|
|
17700
|
+
let best = null;
|
|
17701
|
+
for (const slot of slots) {
|
|
17702
|
+
const cx2 = slot.left + slot.width / 2;
|
|
17703
|
+
const cy = slot.top + slot.height / 2;
|
|
17704
|
+
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;
|
|
17705
|
+
if (!best || dist < best.dist) best = { slot, dist };
|
|
17706
|
+
}
|
|
17707
|
+
return best?.slot ?? null;
|
|
17708
|
+
}
|
|
17709
|
+
function insertButtonAtCollectionIndex(button, insertIndex) {
|
|
17710
|
+
const collection = buttonCollectionOf(button);
|
|
17711
|
+
if (!collection) return null;
|
|
17712
|
+
const items = listVisibleCollectionButtons(collection);
|
|
17713
|
+
const from = items.indexOf(button);
|
|
17714
|
+
if (from < 0) return null;
|
|
17715
|
+
const others = items.filter((el) => el !== button);
|
|
17716
|
+
let index = insertIndex;
|
|
17717
|
+
if (from < insertIndex) index -= 1;
|
|
17718
|
+
if (index <= 0) {
|
|
17719
|
+
const first = others[0];
|
|
17720
|
+
if (first) first.before(button);
|
|
17721
|
+
else collection.append(button);
|
|
17722
|
+
} else if (index >= others.length) {
|
|
17723
|
+
collection.append(button);
|
|
17724
|
+
} else {
|
|
17725
|
+
others[index].before(button);
|
|
17726
|
+
}
|
|
17727
|
+
return listCollectionMembers(collection);
|
|
17728
|
+
}
|
|
17729
|
+
function persistCollectionOrder(collection, content) {
|
|
17730
|
+
const id = collection.getAttribute(COLLECTION_ATTR);
|
|
17731
|
+
if (!id) return null;
|
|
17732
|
+
const collections = readCollections(content);
|
|
17733
|
+
const current = collections[id];
|
|
17734
|
+
const members = listCollectionMembers(collection);
|
|
17735
|
+
const next = {
|
|
17736
|
+
...collections,
|
|
17737
|
+
[id]: { id, members, gap: collection.style.gap || current?.gap || "12px" }
|
|
17738
|
+
};
|
|
17739
|
+
const nextContent = { ...content, [BUTTON_COLLECTIONS_KEY]: JSON.stringify(next) };
|
|
17740
|
+
return { content: nextContent, nodes: [{ key: BUTTON_COLLECTIONS_KEY, text: nextContent[BUTTON_COLLECTIONS_KEY] }] };
|
|
17741
|
+
}
|
|
17742
|
+
function hideButton(el) {
|
|
17743
|
+
if (el.getAttribute("data-ohw-button-hidden") === "") return;
|
|
17744
|
+
el.setAttribute("data-ohw-button-hidden", "");
|
|
17745
|
+
el.style.display = "none";
|
|
17746
|
+
}
|
|
17747
|
+
function syncButtonsFromContent(doc, content) {
|
|
17748
|
+
reconcileButtonCollections(doc, content);
|
|
17749
|
+
applyButtonContentFromContent(doc, content);
|
|
17750
|
+
applyButtonStylesFromContent(doc, content);
|
|
17751
|
+
}
|
|
17752
|
+
function applyButtonContentFromContent(doc, content) {
|
|
17753
|
+
const snapshots = readSnapshots(content);
|
|
17754
|
+
for (const snapshot of Object.values(snapshots)) {
|
|
17755
|
+
const el = findButton(doc, snapshot.id);
|
|
17756
|
+
if (!el) continue;
|
|
17757
|
+
applySnapshotContent(el, snapshot, content);
|
|
17758
|
+
}
|
|
17759
|
+
}
|
|
17760
|
+
function applySnapshotContent(el, snapshot, content) {
|
|
17761
|
+
const href = content[snapshot.id] ?? snapshot.href;
|
|
17762
|
+
if (href) el.setAttribute("href", href);
|
|
17763
|
+
const labelKey = snapshot.labelKey || labelKeyForHrefKey(snapshot.id);
|
|
17764
|
+
if (labelKey && !el.querySelector(`[data-ohw-key="${CSS.escape(labelKey)}"]`)) {
|
|
17765
|
+
const label2 = labelElement2(el);
|
|
17766
|
+
if (label2) label2.setAttribute("data-ohw-key", labelKey);
|
|
17767
|
+
}
|
|
17768
|
+
const text = content[labelKey];
|
|
17769
|
+
if (text === void 0) return;
|
|
17770
|
+
const label = labelElement2(el);
|
|
17771
|
+
if (label) {
|
|
17772
|
+
if (label.getAttribute("data-ohw-key") !== labelKey) label.setAttribute("data-ohw-key", labelKey);
|
|
17773
|
+
if (label.textContent !== text) label.textContent = text;
|
|
17774
|
+
}
|
|
17775
|
+
}
|
|
17776
|
+
function reconcileButtonCollections(doc, content) {
|
|
17777
|
+
const hidden = new Set(readHiddenButtons(content));
|
|
17778
|
+
for (const id of hidden) {
|
|
17779
|
+
const el = findButton(doc, id);
|
|
17780
|
+
if (el) hideButton(el);
|
|
17781
|
+
}
|
|
17782
|
+
const snapshots = readSnapshots(content);
|
|
17783
|
+
const collections = readCollections(content);
|
|
17784
|
+
for (const collectionState of Object.values(collections)) {
|
|
17785
|
+
const live = collectionState.members.map((id) => findButton(doc, id) ?? restoreSnapshot(doc, snapshots[id], content)).filter((el) => Boolean(el && !hidden.has(buttonId(el) ?? "")));
|
|
17786
|
+
if (live.length === 0) continue;
|
|
17787
|
+
if (live.length === 1) {
|
|
17788
|
+
const existing = buttonCollectionOf(live[0]);
|
|
17789
|
+
if (existing) unwrapCollection(existing);
|
|
17790
|
+
continue;
|
|
17791
|
+
}
|
|
17792
|
+
const anchor = live.find((el) => el.isConnected) ?? live[0];
|
|
17793
|
+
let collection = live.map((el) => buttonCollectionOf(el)).find((el) => el?.getAttribute(COLLECTION_ATTR) === collectionState.id) ?? null;
|
|
17794
|
+
if (!collection) {
|
|
17795
|
+
if (!anchor.parentElement) continue;
|
|
17796
|
+
collection = createCollection(doc, collectionState.id, collectionState.gap);
|
|
17797
|
+
anchor.parentElement.insertBefore(collection, anchor);
|
|
17798
|
+
}
|
|
17799
|
+
styleCollection(collection, collectionState.gap);
|
|
17800
|
+
const current = listCollectionMembers(collection);
|
|
17801
|
+
const sameOrder = current.length === live.length && current.every((id, index) => id === buttonId(live[index]));
|
|
17802
|
+
if (!sameOrder) {
|
|
17803
|
+
for (const member of live) collection.append(member);
|
|
17804
|
+
}
|
|
17805
|
+
for (const member of live) setButtonDragAttr(member);
|
|
17806
|
+
}
|
|
17807
|
+
}
|
|
17808
|
+
function restoreSnapshot(doc, snapshot, content) {
|
|
17809
|
+
if (!snapshot) return null;
|
|
17810
|
+
const existing = findButton(doc, snapshot.id);
|
|
17811
|
+
if (existing) {
|
|
17812
|
+
applySnapshotContent(existing, snapshot, content);
|
|
17813
|
+
return existing;
|
|
17814
|
+
}
|
|
17815
|
+
const el = htmlToElement(doc, snapshot.html);
|
|
17816
|
+
if (!el) return null;
|
|
17817
|
+
el.setAttribute("data-ohw-href-key", snapshot.id);
|
|
17818
|
+
const label = labelElement2(el);
|
|
17819
|
+
const labelKey = snapshot.labelKey || labelKeyForHrefKey(snapshot.id);
|
|
17820
|
+
if (label) label.setAttribute("data-ohw-key", labelKey);
|
|
17821
|
+
applySnapshotContent(el, snapshot, content);
|
|
17822
|
+
setButtonDragAttr(el);
|
|
17823
|
+
return el;
|
|
17824
|
+
}
|
|
17825
|
+
function navbarCtasInScope(el) {
|
|
17826
|
+
const scope = el.closest("nav, [data-ohw-nav-root], [data-ohw-nav-drawer]") ?? el.parentElement;
|
|
17827
|
+
if (!scope) return [];
|
|
17828
|
+
return Array.from(scope.querySelectorAll(CTA_BUTTON_SELECTOR)).filter(
|
|
17829
|
+
(button) => isNavbarCta(button) && buttonId(button)
|
|
17830
|
+
);
|
|
17831
|
+
}
|
|
17832
|
+
function ensureNavbarButtonCollection(button, content) {
|
|
17833
|
+
const existing = buttonCollectionOf(button);
|
|
17834
|
+
if (existing) return existing;
|
|
17835
|
+
if (!isNavbarCta(button) || !buttonId(button)) return null;
|
|
17836
|
+
const parent = button.parentElement;
|
|
17837
|
+
if (!parent) return null;
|
|
17838
|
+
const siblings = navbarCtasInScope(button).filter((el) => el.parentElement === parent);
|
|
17839
|
+
if (siblings.length < 2) return null;
|
|
17840
|
+
const id = nextCollectionId(content, button.ownerDocument);
|
|
17841
|
+
const collection = createCollection(button.ownerDocument, id, collectionGap(button, tokensFromButton(button)));
|
|
17842
|
+
siblings[0].before(collection);
|
|
17843
|
+
for (const member of siblings) {
|
|
17844
|
+
collection.append(member);
|
|
17845
|
+
setButtonDragAttr(member);
|
|
17846
|
+
}
|
|
17847
|
+
return collection;
|
|
17848
|
+
}
|
|
17849
|
+
function collectionDragEnabled(el) {
|
|
17850
|
+
if (!isNavbarCta(el) || !buttonId(el)) return false;
|
|
17851
|
+
if (buttonCollectionOf(el)) return true;
|
|
17852
|
+
return navbarCtasInScope(el).length >= 2;
|
|
17853
|
+
}
|
|
17854
|
+
|
|
17855
|
+
// src/lib/item-drag-interaction.ts
|
|
17856
|
+
function disableNativeHrefDrag(el) {
|
|
17857
|
+
if (el.draggable) el.draggable = false;
|
|
17858
|
+
if (el.getAttribute("draggable") !== "false") {
|
|
17859
|
+
el.setAttribute("draggable", "false");
|
|
17860
|
+
}
|
|
17861
|
+
}
|
|
17862
|
+
function clearTextSelection() {
|
|
17863
|
+
const sel = window.getSelection();
|
|
17864
|
+
if (sel && !sel.isCollapsed) sel.removeAllRanges();
|
|
17865
|
+
}
|
|
17866
|
+
function armItemPressDrag() {
|
|
17867
|
+
document.documentElement.setAttribute("data-ohw-footer-press-drag", "");
|
|
17868
|
+
}
|
|
17869
|
+
function lockItemDuringDrag() {
|
|
17870
|
+
document.documentElement.removeAttribute("data-ohw-footer-press-drag");
|
|
17871
|
+
document.documentElement.setAttribute("data-ohw-item-dragging", "");
|
|
17872
|
+
clearTextSelection();
|
|
17873
|
+
}
|
|
17874
|
+
function unlockItemDragInteraction() {
|
|
17875
|
+
const wasDragging = document.documentElement.hasAttribute("data-ohw-item-dragging");
|
|
17876
|
+
document.documentElement.removeAttribute("data-ohw-footer-press-drag");
|
|
17877
|
+
document.documentElement.removeAttribute("data-ohw-item-dragging");
|
|
17878
|
+
if (wasDragging) clearTextSelection();
|
|
17879
|
+
}
|
|
17880
|
+
var armFooterPressDrag = armItemPressDrag;
|
|
17881
|
+
var lockFooterDuringDrag = lockItemDuringDrag;
|
|
17882
|
+
var unlockFooterDragInteraction = unlockItemDragInteraction;
|
|
17883
|
+
|
|
17884
|
+
// src/lib/nav-dnd.ts
|
|
17885
|
+
function listReorderableNavItems(draggedEl) {
|
|
17886
|
+
return listActiveNavbarItems(draggedEl).filter((el) => {
|
|
17887
|
+
const key = el.getAttribute("data-ohw-href-key");
|
|
17888
|
+
return isNavbarHrefKey(key) && !isNestedNavChild(el);
|
|
17889
|
+
});
|
|
17890
|
+
}
|
|
17891
|
+
function resolveParentNavHrefKey(child) {
|
|
17892
|
+
const childrenRoot = child.closest("[data-ohw-nav-children]");
|
|
17893
|
+
const group = childrenRoot?.closest("[data-ohw-nav-group]");
|
|
17894
|
+
if (!group) return null;
|
|
17895
|
+
const trigger = group.querySelector(":scope > [data-ohw-href-key]") ?? Array.from(group.querySelectorAll("[data-ohw-href-key]")).find(
|
|
17896
|
+
(el) => !el.closest("[data-ohw-nav-children]")
|
|
17897
|
+
) ?? null;
|
|
17898
|
+
const key = trigger?.getAttribute("data-ohw-href-key");
|
|
17899
|
+
return key && isNavbarHrefKey(key) ? key : null;
|
|
17900
|
+
}
|
|
17901
|
+
function listNavChildren(parentHrefKey, draggedEl) {
|
|
17902
|
+
const items = listActiveNavbarItems(draggedEl);
|
|
17903
|
+
const parent = items.find((el) => el.getAttribute("data-ohw-href-key") === parentHrefKey);
|
|
17904
|
+
if (!parent) return [];
|
|
17905
|
+
const group = parent.closest("[data-ohw-nav-group]");
|
|
17906
|
+
const childrenRoot = group?.querySelector(":scope > [data-ohw-nav-children]");
|
|
17907
|
+
if (!childrenRoot) return [];
|
|
17908
|
+
return Array.from(childrenRoot.querySelectorAll(":scope > [data-ohw-href-key]")).filter(
|
|
17909
|
+
(el) => isNavbarHrefKey(el.getAttribute("data-ohw-href-key"))
|
|
17910
|
+
);
|
|
17911
|
+
}
|
|
17912
|
+
function isVerticalNavLayout(items, draggedEl) {
|
|
17913
|
+
const visible = items.filter((el) => el.getClientRects().length > 0);
|
|
17914
|
+
if (visible.length >= 2) {
|
|
17915
|
+
const a = visible[0].getBoundingClientRect();
|
|
17916
|
+
const b = visible[1].getBoundingClientRect();
|
|
17917
|
+
const verticalGap = b.top - a.bottom;
|
|
17918
|
+
const horizontalGap = b.left - a.right;
|
|
17919
|
+
return verticalGap > horizontalGap;
|
|
17920
|
+
}
|
|
17921
|
+
const container = getActiveNavbarListContainer(draggedEl);
|
|
17922
|
+
if (!container) return false;
|
|
17923
|
+
const style = window.getComputedStyle(container);
|
|
17924
|
+
return style.flexDirection === "column" || style.flexDirection === "column-reverse";
|
|
17925
|
+
}
|
|
17926
|
+
function buildVerticalRootNavDropSlots(items, draggedEl) {
|
|
17927
|
+
const slots = [];
|
|
17928
|
+
const barThickness = 3;
|
|
17929
|
+
if (items.length === 0) {
|
|
17930
|
+
const container = getActiveNavbarListContainer(draggedEl);
|
|
17931
|
+
if (!container) return slots;
|
|
17932
|
+
const rect = container.getBoundingClientRect();
|
|
17933
|
+
slots.push({
|
|
17934
|
+
insertIndex: 0,
|
|
17935
|
+
parentId: null,
|
|
17936
|
+
left: rect.left,
|
|
17937
|
+
top: rect.top + rect.height / 2 - barThickness / 2,
|
|
17938
|
+
width: Math.max(rect.width, 40),
|
|
17939
|
+
height: barThickness,
|
|
17940
|
+
direction: "horizontal"
|
|
17941
|
+
});
|
|
17942
|
+
return slots;
|
|
17943
|
+
}
|
|
17944
|
+
const edgeGap = (() => {
|
|
17945
|
+
if (items.length < 2) return 16;
|
|
17946
|
+
const a = items[0].getBoundingClientRect();
|
|
17947
|
+
const b = items[1].getBoundingClientRect();
|
|
17948
|
+
return Math.max(0, b.top - a.bottom);
|
|
17949
|
+
})();
|
|
17950
|
+
for (let i = 0; i <= items.length; i++) {
|
|
17951
|
+
let top;
|
|
17952
|
+
let width;
|
|
17953
|
+
let left;
|
|
17954
|
+
if (i === 0) {
|
|
17955
|
+
const first = items[0].getBoundingClientRect();
|
|
17956
|
+
top = first.top - edgeGap / 2 - barThickness / 2;
|
|
17957
|
+
left = first.left;
|
|
17958
|
+
width = first.width;
|
|
17959
|
+
} else if (i === items.length) {
|
|
17960
|
+
const last = items[items.length - 1].getBoundingClientRect();
|
|
17961
|
+
const lastGap = items.length >= 2 ? Math.max(0, last.top - items[items.length - 2].getBoundingClientRect().bottom) : edgeGap;
|
|
17962
|
+
top = last.bottom + lastGap / 2 - barThickness / 2;
|
|
17963
|
+
left = last.left;
|
|
17964
|
+
width = last.width;
|
|
17965
|
+
} else {
|
|
17966
|
+
const prev = items[i - 1].getBoundingClientRect();
|
|
17967
|
+
const next = items[i].getBoundingClientRect();
|
|
17968
|
+
top = (prev.bottom + next.top) / 2 - barThickness / 2;
|
|
17969
|
+
left = Math.min(prev.left, next.left);
|
|
16177
17970
|
width = Math.max(prev.right, next.right) - left;
|
|
16178
17971
|
}
|
|
16179
17972
|
slots.push({
|
|
@@ -16488,7 +18281,7 @@ function useNavItemDrag({
|
|
|
16488
18281
|
document.querySelectorAll(
|
|
16489
18282
|
"nav [data-ohw-href-key], [data-ohw-nav-container] [data-ohw-href-key], [data-ohw-nav-drawer] [data-ohw-href-key]"
|
|
16490
18283
|
).forEach((el) => {
|
|
16491
|
-
if (isNavbarHrefKey(el.getAttribute("data-ohw-href-key"))) {
|
|
18284
|
+
if (isNavbarHrefKey(el.getAttribute("data-ohw-href-key")) || isCtaButton(el)) {
|
|
16492
18285
|
disableNativeHrefDrag(el);
|
|
16493
18286
|
}
|
|
16494
18287
|
});
|
|
@@ -16797,12 +18590,6 @@ var SECTION_DRAG_EXCLUDED_SELECTOR = [
|
|
|
16797
18590
|
"[data-ohw-media-overlay]",
|
|
16798
18591
|
"[data-ohw-media-skeleton]"
|
|
16799
18592
|
].join(", ");
|
|
16800
|
-
function visibleClip(ps) {
|
|
16801
|
-
if (!ps) return null;
|
|
16802
|
-
const top = Math.max(0, ps.headerH - ps.iframeOffsetTop);
|
|
16803
|
-
const bottom = Math.min(window.innerHeight, ps.headerH + ps.canvasH - ps.iframeOffsetTop);
|
|
16804
|
-
return { top, bottom: Math.max(top, bottom) };
|
|
16805
|
-
}
|
|
16806
18593
|
function useSectionDrag({
|
|
16807
18594
|
isEditMode,
|
|
16808
18595
|
editContentRef,
|
|
@@ -16839,7 +18626,7 @@ function useSectionDrag({
|
|
|
16839
18626
|
}, [postToParentRef, stopAutoScroll]);
|
|
16840
18627
|
const updateAutoScroll = (0, import_react17.useCallback)(
|
|
16841
18628
|
(clientY) => {
|
|
16842
|
-
const clip =
|
|
18629
|
+
const clip = getIframeChromeClip(parentScrollRef.current);
|
|
16843
18630
|
let delta = 0;
|
|
16844
18631
|
if (clip) {
|
|
16845
18632
|
const distTop = clientY - clip.top;
|
|
@@ -17045,8 +18832,8 @@ function useSectionDrag({
|
|
|
17045
18832
|
}
|
|
17046
18833
|
|
|
17047
18834
|
// src/ui/footer-container-chrome.tsx
|
|
17048
|
-
var
|
|
17049
|
-
var
|
|
18835
|
+
var import_lucide_react18 = require("lucide-react");
|
|
18836
|
+
var import_jsx_runtime32 = require("react/jsx-runtime");
|
|
17050
18837
|
function FooterContainerChrome({
|
|
17051
18838
|
rect,
|
|
17052
18839
|
onAdd,
|
|
@@ -17054,7 +18841,7 @@ function FooterContainerChrome({
|
|
|
17054
18841
|
}) {
|
|
17055
18842
|
const chromeGap = 6;
|
|
17056
18843
|
const buttonMargin = 7;
|
|
17057
|
-
return /* @__PURE__ */ (0,
|
|
18844
|
+
return /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(TooltipProvider, { delayDuration: 0, children: /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
|
|
17058
18845
|
"div",
|
|
17059
18846
|
{
|
|
17060
18847
|
"data-ohw-footer-container-chrome": "",
|
|
@@ -17066,8 +18853,8 @@ function FooterContainerChrome({
|
|
|
17066
18853
|
width: rect.width + chromeGap * 2,
|
|
17067
18854
|
height: rect.height + chromeGap * 2
|
|
17068
18855
|
},
|
|
17069
|
-
children: /* @__PURE__ */ (0,
|
|
17070
|
-
/* @__PURE__ */ (0,
|
|
18856
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)(Tooltip, { children: [
|
|
18857
|
+
/* @__PURE__ */ (0, import_jsx_runtime32.jsx)(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
|
|
17071
18858
|
"button",
|
|
17072
18859
|
{
|
|
17073
18860
|
type: "button",
|
|
@@ -17086,10 +18873,10 @@ function FooterContainerChrome({
|
|
|
17086
18873
|
if (addDisabled) return;
|
|
17087
18874
|
onAdd();
|
|
17088
18875
|
},
|
|
17089
|
-
children: /* @__PURE__ */ (0,
|
|
18876
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(import_lucide_react18.Plus, { className: "size-4 shrink-0 text-foreground", "aria-hidden": true })
|
|
17090
18877
|
}
|
|
17091
18878
|
) }),
|
|
17092
|
-
/* @__PURE__ */ (0,
|
|
18879
|
+
/* @__PURE__ */ (0, import_jsx_runtime32.jsx)(TooltipContent, { side: "bottom", sideOffset: 9, children: addDisabled ? "Maximum columns reached" : "Add item" })
|
|
17093
18880
|
] })
|
|
17094
18881
|
}
|
|
17095
18882
|
) });
|
|
@@ -17251,7 +19038,14 @@ function collectEditableNodes(extraContent, root = document) {
|
|
|
17251
19038
|
// so collecting the DOM alone left them behind: the draft knew the row was showing icons and
|
|
17252
19039
|
// had gained an item, and the published page went back to the template's own (OHH-736).
|
|
17253
19040
|
SOCIALS_ORDER_KEY,
|
|
17254
|
-
SOCIALS_DISPLAY_KEY
|
|
19041
|
+
SOCIALS_DISPLAY_KEY,
|
|
19042
|
+
// Button variant/size tokens and per-CTA assignments — JSON in editContent, applied on hydrate.
|
|
19043
|
+
BUTTON_VARIANTS_KEY,
|
|
19044
|
+
BUTTON_SIZES_KEY,
|
|
19045
|
+
BUTTON_ASSIGNMENTS_KEY,
|
|
19046
|
+
BUTTON_COLLECTIONS_KEY,
|
|
19047
|
+
BUTTON_SNAPSHOTS_KEY,
|
|
19048
|
+
BUTTON_HIDDEN_KEY
|
|
17255
19049
|
]) {
|
|
17256
19050
|
const text = extraContent[key];
|
|
17257
19051
|
if (typeof text === "string" && text.length > 0) {
|
|
@@ -17571,14 +19365,14 @@ function deleteSelectedNavFooterItem(deps) {
|
|
|
17571
19365
|
}
|
|
17572
19366
|
|
|
17573
19367
|
// src/ui/navbar-container-chrome.tsx
|
|
17574
|
-
var
|
|
17575
|
-
var
|
|
19368
|
+
var import_lucide_react19 = require("lucide-react");
|
|
19369
|
+
var import_jsx_runtime33 = require("react/jsx-runtime");
|
|
17576
19370
|
function NavbarContainerChrome({
|
|
17577
19371
|
rect,
|
|
17578
19372
|
onAdd
|
|
17579
19373
|
}) {
|
|
17580
19374
|
const chromeGap = 6;
|
|
17581
|
-
return /* @__PURE__ */ (0,
|
|
19375
|
+
return /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
|
|
17582
19376
|
"div",
|
|
17583
19377
|
{
|
|
17584
19378
|
"data-ohw-navbar-container-chrome": "",
|
|
@@ -17590,7 +19384,7 @@ function NavbarContainerChrome({
|
|
|
17590
19384
|
width: rect.width + chromeGap * 2,
|
|
17591
19385
|
height: rect.height + chromeGap * 2
|
|
17592
19386
|
},
|
|
17593
|
-
children: /* @__PURE__ */ (0,
|
|
19387
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
|
|
17594
19388
|
"button",
|
|
17595
19389
|
{
|
|
17596
19390
|
type: "button",
|
|
@@ -17607,7 +19401,7 @@ function NavbarContainerChrome({
|
|
|
17607
19401
|
e.stopPropagation();
|
|
17608
19402
|
onAdd();
|
|
17609
19403
|
},
|
|
17610
|
-
children: /* @__PURE__ */ (0,
|
|
19404
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(import_lucide_react19.Plus, { className: "size-4 shrink-0 text-foreground", "aria-hidden": true })
|
|
17611
19405
|
}
|
|
17612
19406
|
)
|
|
17613
19407
|
}
|
|
@@ -17616,7 +19410,7 @@ function NavbarContainerChrome({
|
|
|
17616
19410
|
|
|
17617
19411
|
// src/ui/drop-indicator.tsx
|
|
17618
19412
|
var React11 = __toESM(require("react"), 1);
|
|
17619
|
-
var
|
|
19413
|
+
var import_jsx_runtime34 = require("react/jsx-runtime");
|
|
17620
19414
|
var dropIndicatorVariants = cva(
|
|
17621
19415
|
"ov-gap-line pointer-events-none shrink-0 transition-opacity duration-150",
|
|
17622
19416
|
{
|
|
@@ -17640,7 +19434,7 @@ var dropIndicatorVariants = cva(
|
|
|
17640
19434
|
);
|
|
17641
19435
|
var DropIndicator = React11.forwardRef(
|
|
17642
19436
|
({ className, direction, state, ...props }, ref) => {
|
|
17643
|
-
return /* @__PURE__ */ (0,
|
|
19437
|
+
return /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
|
|
17644
19438
|
"div",
|
|
17645
19439
|
{
|
|
17646
19440
|
ref,
|
|
@@ -17657,7 +19451,7 @@ var DropIndicator = React11.forwardRef(
|
|
|
17657
19451
|
DropIndicator.displayName = "DropIndicator";
|
|
17658
19452
|
|
|
17659
19453
|
// src/ui/badge.tsx
|
|
17660
|
-
var
|
|
19454
|
+
var import_jsx_runtime35 = require("react/jsx-runtime");
|
|
17661
19455
|
var badgeVariants = cva(
|
|
17662
19456
|
"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",
|
|
17663
19457
|
{
|
|
@@ -17675,12 +19469,12 @@ var badgeVariants = cva(
|
|
|
17675
19469
|
}
|
|
17676
19470
|
);
|
|
17677
19471
|
function Badge({ className, variant, ...props }) {
|
|
17678
|
-
return /* @__PURE__ */ (0,
|
|
19472
|
+
return /* @__PURE__ */ (0, import_jsx_runtime35.jsx)("div", { className: cn(badgeVariants({ variant }), className), ...props });
|
|
17679
19473
|
}
|
|
17680
19474
|
|
|
17681
19475
|
// src/OhhwellsBridge.tsx
|
|
17682
|
-
var
|
|
17683
|
-
var
|
|
19476
|
+
var import_lucide_react20 = require("lucide-react");
|
|
19477
|
+
var import_jsx_runtime36 = require("react/jsx-runtime");
|
|
17684
19478
|
var PRIMARY5 = "#0885FE";
|
|
17685
19479
|
var IMAGE_FADE_MS = 300;
|
|
17686
19480
|
var MEDIA_SETTLE_TIMEOUT_MS = 2500;
|
|
@@ -17802,7 +19596,7 @@ function duplicateSchedulingWidget(instanceId, scheduleId) {
|
|
|
17802
19596
|
schedulingRoots.set(container, root);
|
|
17803
19597
|
(0, import_react_dom4.flushSync)(() => {
|
|
17804
19598
|
root.render(
|
|
17805
|
-
/* @__PURE__ */ (0,
|
|
19599
|
+
/* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
|
|
17806
19600
|
SchedulingWidget,
|
|
17807
19601
|
{
|
|
17808
19602
|
notifyOnConnect: false,
|
|
@@ -17845,21 +19639,10 @@ function parseSchedulingInsertAfter(insertAfter) {
|
|
|
17845
19639
|
insertBefore: insertAfter.slice(idx + INSERT_BEFORE_MARKER.length)
|
|
17846
19640
|
};
|
|
17847
19641
|
}
|
|
17848
|
-
function
|
|
17849
|
-
|
|
17850
|
-
const
|
|
17851
|
-
|
|
17852
|
-
return { effectiveInsertAfter, insertBefore };
|
|
17853
|
-
}
|
|
17854
|
-
function getSchedulingMountPoint(insertAfter) {
|
|
17855
|
-
const { anchor } = parseSchedulingInsertAfter(insertAfter);
|
|
17856
|
-
let anchorEl = document.querySelector(`[data-ohw-section="${anchor}"]`);
|
|
17857
|
-
if (!anchorEl && anchor === "scheduling") {
|
|
17858
|
-
const widgets = Array.from(document.querySelectorAll('[data-ohw-section^="scheduling-"]'));
|
|
17859
|
-
anchorEl = widgets.at(-1) ?? null;
|
|
17860
|
-
}
|
|
17861
|
-
if (!anchorEl) return null;
|
|
17862
|
-
return anchorEl.closest('[data-ohw-section-container="scheduling"]') ?? anchorEl;
|
|
19642
|
+
function resolveEntryAnchor(entry) {
|
|
19643
|
+
if (entry.anchorId !== void 0) return { anchorId: entry.anchorId, beforeId: entry.beforeId ?? null };
|
|
19644
|
+
const parsed = parseSchedulingInsertAfter(entry.insertAfter);
|
|
19645
|
+
return { anchorId: parsed.anchor, beforeId: parsed.insertBefore };
|
|
17863
19646
|
}
|
|
17864
19647
|
function schedulingMountDepth(insertAfter) {
|
|
17865
19648
|
if (!insertAfter.includes(INSERT_BEFORE_MARKER)) return 0;
|
|
@@ -17876,8 +19659,7 @@ function getPageSchedulingEntries(raw) {
|
|
|
17876
19659
|
}
|
|
17877
19660
|
}
|
|
17878
19661
|
function isSchedulingWidgetMissing(entry) {
|
|
17879
|
-
|
|
17880
|
-
return !document.querySelector(`[data-ohw-section="${schedulingSectionId(effectiveInsertAfter)}"]`);
|
|
19662
|
+
return !document.querySelector(`[data-ohw-section="${schedulingSectionId(entry.insertAfter)}"]`);
|
|
17881
19663
|
}
|
|
17882
19664
|
function hasMissingSchedulingWidgets(entries) {
|
|
17883
19665
|
return entries.some(isSchedulingWidgetMissing);
|
|
@@ -17915,17 +19697,18 @@ function initSectionsFromContent(content, removeExisting = false, currentPath =
|
|
|
17915
19697
|
} catch {
|
|
17916
19698
|
}
|
|
17917
19699
|
}
|
|
17918
|
-
function mountSchedulingWidget(
|
|
17919
|
-
const
|
|
17920
|
-
const sectionId = schedulingSectionId(
|
|
19700
|
+
function mountSchedulingWidget(anchorId, notifyOnConnect = false, scheduleId, beforeId, existingWidgetId) {
|
|
19701
|
+
const widgetId = existingWidgetId ?? (beforeId ? `${anchorId}${INSERT_BEFORE_MARKER}${beforeId}` : anchorId);
|
|
19702
|
+
const sectionId = schedulingSectionId(widgetId);
|
|
17921
19703
|
if (document.querySelector(`[data-ohw-section="${sectionId}"]`)) return false;
|
|
17922
|
-
const
|
|
17923
|
-
if (!
|
|
19704
|
+
const anchorEl = document.querySelector(`[data-ohw-section="${anchorId}"]`);
|
|
19705
|
+
if (!anchorEl) return false;
|
|
19706
|
+
const mountPoint = anchorEl.closest('[data-ohw-section-container="scheduling"]') ?? anchorEl;
|
|
17924
19707
|
const container = document.createElement("div");
|
|
17925
19708
|
container.dataset.ohwSectionContainer = "scheduling";
|
|
17926
19709
|
container.dataset.ohwInstance = sectionId;
|
|
17927
|
-
if (
|
|
17928
|
-
const beforeAnchor = document.querySelector(`[data-ohw-section="${
|
|
19710
|
+
if (beforeId) {
|
|
19711
|
+
const beforeAnchor = document.querySelector(`[data-ohw-section="${beforeId}"]`);
|
|
17929
19712
|
const beforePoint = beforeAnchor?.closest('[data-ohw-section-container="scheduling"]') ?? beforeAnchor;
|
|
17930
19713
|
if (!beforePoint) return false;
|
|
17931
19714
|
beforePoint.insertAdjacentElement("beforebegin", container);
|
|
@@ -17936,20 +19719,26 @@ function mountSchedulingWidget(insertAfter, notifyOnConnect = false, scheduleId,
|
|
|
17936
19719
|
}
|
|
17937
19720
|
tail.insertAdjacentElement("afterend", container);
|
|
17938
19721
|
}
|
|
17939
|
-
|
|
17940
|
-
|
|
17941
|
-
|
|
17942
|
-
|
|
17943
|
-
|
|
17944
|
-
|
|
17945
|
-
|
|
17946
|
-
|
|
17947
|
-
|
|
17948
|
-
|
|
17949
|
-
|
|
17950
|
-
|
|
17951
|
-
|
|
17952
|
-
|
|
19722
|
+
try {
|
|
19723
|
+
const root = (0, import_client2.createRoot)(container);
|
|
19724
|
+
schedulingRoots.set(container, root);
|
|
19725
|
+
(0, import_react_dom4.flushSync)(() => {
|
|
19726
|
+
root.render(
|
|
19727
|
+
/* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
|
|
19728
|
+
SchedulingWidget,
|
|
19729
|
+
{
|
|
19730
|
+
notifyOnConnect,
|
|
19731
|
+
initialScheduleId: scheduleId,
|
|
19732
|
+
insertAfter: widgetId
|
|
19733
|
+
}
|
|
19734
|
+
)
|
|
19735
|
+
);
|
|
19736
|
+
});
|
|
19737
|
+
} catch (err) {
|
|
19738
|
+
console.error("[ow:scheduling] render threw", err);
|
|
19739
|
+
container.remove();
|
|
19740
|
+
return false;
|
|
19741
|
+
}
|
|
17953
19742
|
const tracker = getSectionsTracker();
|
|
17954
19743
|
let sections = [];
|
|
17955
19744
|
try {
|
|
@@ -17957,10 +19746,12 @@ function mountSchedulingWidget(insertAfter, notifyOnConnect = false, scheduleId,
|
|
|
17957
19746
|
} catch {
|
|
17958
19747
|
}
|
|
17959
19748
|
const inEditor = typeof window !== "undefined" && window.self !== window.top;
|
|
17960
|
-
if (inEditor && !sections.find((s) => s.type === "scheduling" && s.insertAfter ===
|
|
19749
|
+
if (inEditor && !sections.find((s) => s.type === "scheduling" && s.insertAfter === widgetId)) {
|
|
17961
19750
|
sections.push({
|
|
17962
19751
|
type: "scheduling",
|
|
17963
|
-
insertAfter:
|
|
19752
|
+
insertAfter: widgetId,
|
|
19753
|
+
anchorId,
|
|
19754
|
+
beforeId: beforeId ?? null,
|
|
17964
19755
|
pagePath: window.location.pathname,
|
|
17965
19756
|
...scheduleId ? { scheduleId } : {}
|
|
17966
19757
|
});
|
|
@@ -17974,7 +19765,8 @@ function mountSchedulingEntries(entries, notifyOnConnect = false) {
|
|
|
17974
19765
|
for (let i = pending.length - 1; i >= 0; i--) {
|
|
17975
19766
|
const entry = pending[i];
|
|
17976
19767
|
const shouldNotify = typeof notifyOnConnect === "function" ? notifyOnConnect(entry) : notifyOnConnect;
|
|
17977
|
-
|
|
19768
|
+
const { anchorId, beforeId } = resolveEntryAnchor(entry);
|
|
19769
|
+
if (mountSchedulingWidget(anchorId, shouldNotify, entry.scheduleId ?? null, beforeId, entry.insertAfter)) {
|
|
17978
19770
|
pending.splice(i, 1);
|
|
17979
19771
|
}
|
|
17980
19772
|
}
|
|
@@ -18103,8 +19895,8 @@ function lockVideoBox(video) {
|
|
|
18103
19895
|
}
|
|
18104
19896
|
const fit = video.style.objectFit || getComputedStyle(video).objectFit;
|
|
18105
19897
|
const bg = getComputedStyle(video).backgroundColor;
|
|
18106
|
-
const
|
|
18107
|
-
if (fit === "contain" &&
|
|
19898
|
+
const isTransparent2 = bg === "rgba(0, 0, 0, 0)" || bg === "transparent" || !bg;
|
|
19899
|
+
if (fit === "contain" && isTransparent2) {
|
|
18108
19900
|
video.style.backgroundColor = "var(--color-dark, #000)";
|
|
18109
19901
|
}
|
|
18110
19902
|
}
|
|
@@ -18151,6 +19943,11 @@ function applyLinkByKey(key, val) {
|
|
|
18151
19943
|
hrefAnchors.forEach((el) => applyLinkHref(el, val));
|
|
18152
19944
|
}
|
|
18153
19945
|
}
|
|
19946
|
+
function isInsideLinkEditor(target) {
|
|
19947
|
+
return Boolean(
|
|
19948
|
+
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"]')
|
|
19949
|
+
);
|
|
19950
|
+
}
|
|
18154
19951
|
function isInsideFloatingPanel(target) {
|
|
18155
19952
|
return Boolean(target.closest("[data-ohw-floating-panel]"));
|
|
18156
19953
|
}
|
|
@@ -18158,11 +19955,6 @@ function isPointOverFloatingPanel(clientX, clientY) {
|
|
|
18158
19955
|
const el = document.elementFromPoint(clientX, clientY);
|
|
18159
19956
|
return Boolean(el instanceof Element && el.closest("[data-ohw-floating-panel]"));
|
|
18160
19957
|
}
|
|
18161
|
-
function isInsideLinkEditor(target) {
|
|
18162
|
-
return Boolean(
|
|
18163
|
-
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"]')
|
|
18164
|
-
);
|
|
18165
|
-
}
|
|
18166
19958
|
function getHrefKeyFromElement(el) {
|
|
18167
19959
|
if (!el) return null;
|
|
18168
19960
|
const anchor = el.closest("[data-ohw-href-key]");
|
|
@@ -18254,7 +20046,10 @@ function listNavigationItems() {
|
|
|
18254
20046
|
).filter((el) => isNavigationItem2(el));
|
|
18255
20047
|
}
|
|
18256
20048
|
function getNavigationItemReorderState(anchor) {
|
|
18257
|
-
if (isCtaButton(anchor))
|
|
20049
|
+
if (isCtaButton(anchor)) {
|
|
20050
|
+
if (!collectionDragEnabled(anchor)) return { key: null, disabled: true };
|
|
20051
|
+
return { key: buttonId(anchor), disabled: false };
|
|
20052
|
+
}
|
|
18258
20053
|
return getReorderHandleStateFromAnchor(anchor);
|
|
18259
20054
|
}
|
|
18260
20055
|
function getReorderHandleState(el) {
|
|
@@ -18353,6 +20148,12 @@ function isPointOverNavigation(x, y) {
|
|
|
18353
20148
|
const r2 = panel.getBoundingClientRect();
|
|
18354
20149
|
if (x >= r2.left && x <= r2.right && y >= r2.top && y <= r2.bottom) return true;
|
|
18355
20150
|
}
|
|
20151
|
+
for (const el of document.querySelectorAll('[data-ohw-role="navbar-button"]')) {
|
|
20152
|
+
const r2 = el.getBoundingClientRect();
|
|
20153
|
+
if (r2.width > 0 && r2.height > 0 && x >= r2.left && x <= r2.right && y >= r2.top && y <= r2.bottom) {
|
|
20154
|
+
return true;
|
|
20155
|
+
}
|
|
20156
|
+
}
|
|
18356
20157
|
return false;
|
|
18357
20158
|
}
|
|
18358
20159
|
function findHoveredNavOrFooterContainer(x, y) {
|
|
@@ -18432,7 +20233,7 @@ function getNavigationSelectionParent(el) {
|
|
|
18432
20233
|
if (!isFooterLinksContainer(el) && (el.hasAttribute("data-ohw-footer-col") || el.hasAttribute("data-ohw-footer-column") || isInferredFooterGroup2(el))) {
|
|
18433
20234
|
return getFooterLinksContainer();
|
|
18434
20235
|
}
|
|
18435
|
-
if (el.hasAttribute("data-ohw-nav-container") || el.hasAttribute("data-ohw-nav-drawer") || isFooterLinksContainer(el)) {
|
|
20236
|
+
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)) {
|
|
18436
20237
|
return getNavigationRoot(el);
|
|
18437
20238
|
}
|
|
18438
20239
|
return null;
|
|
@@ -18654,7 +20455,6 @@ var ICONS = {
|
|
|
18654
20455
|
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"/>',
|
|
18655
20456
|
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"/>'
|
|
18656
20457
|
};
|
|
18657
|
-
var HEIGHT_SETTLE_DELAYS = [150, 400, 800];
|
|
18658
20458
|
var SELECTION_CHROME_GAP2 = 4;
|
|
18659
20459
|
var TOOLBAR_STROKE_GAP2 = 4;
|
|
18660
20460
|
var TOOLBAR_OFFSET_FROM_ELEMENT = SELECTION_CHROME_GAP2 + TOOLBAR_STROKE_GAP2;
|
|
@@ -18686,7 +20486,7 @@ function EditGlowChrome({
|
|
|
18686
20486
|
hideHandle = false
|
|
18687
20487
|
}) {
|
|
18688
20488
|
const GAP = SELECTION_CHROME_GAP2;
|
|
18689
|
-
return /* @__PURE__ */ (0,
|
|
20489
|
+
return /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)(
|
|
18690
20490
|
"div",
|
|
18691
20491
|
{
|
|
18692
20492
|
ref: elRef,
|
|
@@ -18701,7 +20501,7 @@ function EditGlowChrome({
|
|
|
18701
20501
|
zIndex: 2147483646
|
|
18702
20502
|
},
|
|
18703
20503
|
children: [
|
|
18704
|
-
/* @__PURE__ */ (0,
|
|
20504
|
+
/* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
|
|
18705
20505
|
"div",
|
|
18706
20506
|
{
|
|
18707
20507
|
style: {
|
|
@@ -18715,7 +20515,7 @@ function EditGlowChrome({
|
|
|
18715
20515
|
}
|
|
18716
20516
|
}
|
|
18717
20517
|
),
|
|
18718
|
-
reorderHrefKey && !hideHandle && /* @__PURE__ */ (0,
|
|
20518
|
+
reorderHrefKey && !hideHandle && /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
|
|
18719
20519
|
"div",
|
|
18720
20520
|
{
|
|
18721
20521
|
"data-ohw-drag-handle-container": "",
|
|
@@ -18727,7 +20527,7 @@ function EditGlowChrome({
|
|
|
18727
20527
|
transform: "translate(calc(-100% - 7px), -50%)",
|
|
18728
20528
|
pointerEvents: dragDisabled ? "none" : "auto"
|
|
18729
20529
|
},
|
|
18730
|
-
children: /* @__PURE__ */ (0,
|
|
20530
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
|
|
18731
20531
|
DragHandle,
|
|
18732
20532
|
{
|
|
18733
20533
|
"aria-label": `Reorder ${reorderHrefKey}`,
|
|
@@ -18741,22 +20541,12 @@ function EditGlowChrome({
|
|
|
18741
20541
|
}
|
|
18742
20542
|
);
|
|
18743
20543
|
}
|
|
18744
|
-
function getIframeVisibleClip(parentScroll) {
|
|
18745
|
-
if (!parentScroll) return null;
|
|
18746
|
-
const { iframeOffsetTop, headerH: visibleCanvasTop, canvasH } = parentScroll;
|
|
18747
|
-
const clipTop = Math.max(0, visibleCanvasTop - iframeOffsetTop);
|
|
18748
|
-
const clipBottom = Math.min(
|
|
18749
|
-
window.innerHeight,
|
|
18750
|
-
visibleCanvasTop + canvasH - iframeOffsetTop
|
|
18751
|
-
);
|
|
18752
|
-
return { top: clipTop, bottom: Math.max(clipTop, clipBottom) };
|
|
18753
|
-
}
|
|
18754
20544
|
function isRectOutsideClip(rect, clip) {
|
|
18755
20545
|
if (!clip) return false;
|
|
18756
20546
|
return rect.bottom < clip.top || rect.top > clip.bottom;
|
|
18757
20547
|
}
|
|
18758
20548
|
function applyVisibleViewport(el, parentScroll) {
|
|
18759
|
-
const clip =
|
|
20549
|
+
const clip = getIframeChromeClip(parentScroll);
|
|
18760
20550
|
const top = clip?.top ?? 0;
|
|
18761
20551
|
const height = clip ? clip.bottom - clip.top : window.innerHeight;
|
|
18762
20552
|
el.style.top = `${top}px`;
|
|
@@ -18796,7 +20586,7 @@ function clampToolbarLeft(centerX, toolbarWidth) {
|
|
|
18796
20586
|
function calcToolbarPos(rect, parentScroll, toolbarW = 306) {
|
|
18797
20587
|
const GAP = TOOLBAR_OFFSET_FROM_ELEMENT;
|
|
18798
20588
|
const APPROX_H = 32;
|
|
18799
|
-
const clip =
|
|
20589
|
+
const clip = getIframeChromeClip(parentScroll);
|
|
18800
20590
|
const clipTop = clip?.top ?? 0;
|
|
18801
20591
|
const canvasTopInIframe = parentScroll != null ? parentScroll.headerH - parentScroll.iframeOffsetTop : 0;
|
|
18802
20592
|
const visibleTop = rect.top - canvasTopInIframe;
|
|
@@ -18941,7 +20731,7 @@ function FloatingToolbar({
|
|
|
18941
20731
|
return () => ro.disconnect();
|
|
18942
20732
|
}, [showEditLink, activeCommands]);
|
|
18943
20733
|
const { top, left, transform } = calcToolbarPos(rect, parentScroll, measuredW);
|
|
18944
|
-
return /* @__PURE__ */ (0,
|
|
20734
|
+
return /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
|
|
18945
20735
|
"div",
|
|
18946
20736
|
{
|
|
18947
20737
|
ref: setRefs,
|
|
@@ -18953,12 +20743,12 @@ function FloatingToolbar({
|
|
|
18953
20743
|
zIndex: 2147483647,
|
|
18954
20744
|
pointerEvents: "auto"
|
|
18955
20745
|
},
|
|
18956
|
-
children: /* @__PURE__ */ (0,
|
|
18957
|
-
TOOLBAR_GROUPS.map((btns, gi) => /* @__PURE__ */ (0,
|
|
18958
|
-
gi > 0 && /* @__PURE__ */ (0,
|
|
20746
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)(CustomToolbar, { children: [
|
|
20747
|
+
TOOLBAR_GROUPS.map((btns, gi) => /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)(import_react19.default.Fragment, { children: [
|
|
20748
|
+
gi > 0 && /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(CustomToolbarDivider, {}),
|
|
18959
20749
|
btns.map((btn) => {
|
|
18960
20750
|
const isActive = activeCommands.has(btn.cmd);
|
|
18961
|
-
return /* @__PURE__ */ (0,
|
|
20751
|
+
return /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
|
|
18962
20752
|
CustomToolbarButton,
|
|
18963
20753
|
{
|
|
18964
20754
|
title: btn.title,
|
|
@@ -18967,7 +20757,7 @@ function FloatingToolbar({
|
|
|
18967
20757
|
e.preventDefault();
|
|
18968
20758
|
onCommand(btn.cmd);
|
|
18969
20759
|
},
|
|
18970
|
-
children: /* @__PURE__ */ (0,
|
|
20760
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
|
|
18971
20761
|
"svg",
|
|
18972
20762
|
{
|
|
18973
20763
|
width: "16",
|
|
@@ -18988,7 +20778,7 @@ function FloatingToolbar({
|
|
|
18988
20778
|
);
|
|
18989
20779
|
})
|
|
18990
20780
|
] }, gi)),
|
|
18991
|
-
showEditLink ? /* @__PURE__ */ (0,
|
|
20781
|
+
showEditLink ? /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
|
|
18992
20782
|
CustomToolbarButton,
|
|
18993
20783
|
{
|
|
18994
20784
|
type: "button",
|
|
@@ -19002,7 +20792,7 @@ function FloatingToolbar({
|
|
|
19002
20792
|
e.preventDefault();
|
|
19003
20793
|
e.stopPropagation();
|
|
19004
20794
|
},
|
|
19005
|
-
children: /* @__PURE__ */ (0,
|
|
20795
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(import_lucide_react20.Link, { className: "size-4 shrink-0", "aria-hidden": true })
|
|
19006
20796
|
}
|
|
19007
20797
|
) : null
|
|
19008
20798
|
] })
|
|
@@ -19019,7 +20809,7 @@ function StateToggle({
|
|
|
19019
20809
|
states,
|
|
19020
20810
|
onStateChange
|
|
19021
20811
|
}) {
|
|
19022
|
-
return /* @__PURE__ */ (0,
|
|
20812
|
+
return /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
|
|
19023
20813
|
ToggleGroup,
|
|
19024
20814
|
{
|
|
19025
20815
|
"data-ohw-state-toggle": "",
|
|
@@ -19033,11 +20823,12 @@ function StateToggle({
|
|
|
19033
20823
|
left: rect.right - 8,
|
|
19034
20824
|
transform: "translateX(-100%)"
|
|
19035
20825
|
},
|
|
19036
|
-
children: states.map((state) => /* @__PURE__ */ (0,
|
|
20826
|
+
children: states.map((state) => /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(ToggleGroupItem, { value: state, size: "sm", children: state }, state))
|
|
19037
20827
|
}
|
|
19038
20828
|
);
|
|
19039
20829
|
}
|
|
19040
20830
|
var contentCache = /* @__PURE__ */ new Map();
|
|
20831
|
+
var fetchedContentPaths = /* @__PURE__ */ new Set();
|
|
19041
20832
|
var brandingCache = /* @__PURE__ */ new Map();
|
|
19042
20833
|
var OHW_LOADER_STYLE = {
|
|
19043
20834
|
position: "fixed",
|
|
@@ -19049,9 +20840,9 @@ var OHW_LOADER_STYLE = {
|
|
|
19049
20840
|
justifyContent: "center"
|
|
19050
20841
|
};
|
|
19051
20842
|
function OhwLoaderSpinner() {
|
|
19052
|
-
return /* @__PURE__ */ (0,
|
|
19053
|
-
/* @__PURE__ */ (0,
|
|
19054
|
-
/* @__PURE__ */ (0,
|
|
20843
|
+
return /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)("svg", { width: "28", height: "28", viewBox: "0 0 28 28", fill: "none", "aria-hidden": true, children: [
|
|
20844
|
+
/* @__PURE__ */ (0, import_jsx_runtime36.jsx)("circle", { cx: "14", cy: "14", r: "11", stroke: "#E7E5E4", strokeWidth: "3" }),
|
|
20845
|
+
/* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
|
|
19055
20846
|
"circle",
|
|
19056
20847
|
{
|
|
19057
20848
|
cx: "14",
|
|
@@ -19061,7 +20852,7 @@ function OhwLoaderSpinner() {
|
|
|
19061
20852
|
strokeWidth: "3",
|
|
19062
20853
|
strokeDasharray: "17 52",
|
|
19063
20854
|
strokeLinecap: "round",
|
|
19064
|
-
children: /* @__PURE__ */ (0,
|
|
20855
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
|
|
19065
20856
|
"animateTransform",
|
|
19066
20857
|
{
|
|
19067
20858
|
attributeName: "transform",
|
|
@@ -19077,7 +20868,7 @@ function OhwLoaderSpinner() {
|
|
|
19077
20868
|
] });
|
|
19078
20869
|
}
|
|
19079
20870
|
function OhwBrandMark() {
|
|
19080
|
-
return /* @__PURE__ */ (0,
|
|
20871
|
+
return /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)(
|
|
19081
20872
|
"svg",
|
|
19082
20873
|
{
|
|
19083
20874
|
width: "16",
|
|
@@ -19088,7 +20879,7 @@ function OhwBrandMark() {
|
|
|
19088
20879
|
style: { display: "block", flexShrink: 0 },
|
|
19089
20880
|
xmlns: "http://www.w3.org/2000/svg",
|
|
19090
20881
|
children: [
|
|
19091
|
-
/* @__PURE__ */ (0,
|
|
20882
|
+
/* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
|
|
19092
20883
|
"mask",
|
|
19093
20884
|
{
|
|
19094
20885
|
id: "ohw-badge-mark",
|
|
@@ -19098,15 +20889,15 @@ function OhwBrandMark() {
|
|
|
19098
20889
|
y: "0",
|
|
19099
20890
|
width: "48",
|
|
19100
20891
|
height: "48",
|
|
19101
|
-
children: /* @__PURE__ */ (0,
|
|
20892
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime36.jsx)("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" })
|
|
19102
20893
|
}
|
|
19103
20894
|
),
|
|
19104
|
-
/* @__PURE__ */ (0,
|
|
19105
|
-
/* @__PURE__ */ (0,
|
|
19106
|
-
/* @__PURE__ */ (0,
|
|
19107
|
-
/* @__PURE__ */ (0,
|
|
19108
|
-
/* @__PURE__ */ (0,
|
|
19109
|
-
/* @__PURE__ */ (0,
|
|
20895
|
+
/* @__PURE__ */ (0, import_jsx_runtime36.jsxs)("g", { mask: "url(#ohw-badge-mark)", children: [
|
|
20896
|
+
/* @__PURE__ */ (0, import_jsx_runtime36.jsx)("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" }),
|
|
20897
|
+
/* @__PURE__ */ (0, import_jsx_runtime36.jsx)("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" }),
|
|
20898
|
+
/* @__PURE__ */ (0, import_jsx_runtime36.jsx)("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" }),
|
|
20899
|
+
/* @__PURE__ */ (0, import_jsx_runtime36.jsx)("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" }),
|
|
20900
|
+
/* @__PURE__ */ (0, import_jsx_runtime36.jsx)("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" })
|
|
19110
20901
|
] })
|
|
19111
20902
|
]
|
|
19112
20903
|
}
|
|
@@ -19143,7 +20934,7 @@ var OHW_BADGE_LABEL_STYLE = {
|
|
|
19143
20934
|
whiteSpace: "nowrap"
|
|
19144
20935
|
};
|
|
19145
20936
|
function MadeWithOhhWells() {
|
|
19146
|
-
return /* @__PURE__ */ (0,
|
|
20937
|
+
return /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)(
|
|
19147
20938
|
"a",
|
|
19148
20939
|
{
|
|
19149
20940
|
href: "https://ohhwells.com",
|
|
@@ -19153,8 +20944,8 @@ function MadeWithOhhWells() {
|
|
|
19153
20944
|
"data-ohw-badge": "",
|
|
19154
20945
|
style: OHW_BADGE_STYLE,
|
|
19155
20946
|
children: [
|
|
19156
|
-
/* @__PURE__ */ (0,
|
|
19157
|
-
/* @__PURE__ */ (0,
|
|
20947
|
+
/* @__PURE__ */ (0, import_jsx_runtime36.jsx)(OhwBrandMark, {}),
|
|
20948
|
+
/* @__PURE__ */ (0, import_jsx_runtime36.jsx)("span", { style: OHW_BADGE_LABEL_STYLE, children: "Made with OhhWells" })
|
|
19158
20949
|
]
|
|
19159
20950
|
}
|
|
19160
20951
|
);
|
|
@@ -19641,13 +21432,6 @@ function OhhwellsBridge() {
|
|
|
19641
21432
|
const [isItemDragging, setIsItemDragging] = (0, import_react19.useState)(false);
|
|
19642
21433
|
const [isFooterFrameSelection, setIsFooterFrameSelection] = (0, import_react19.useState)(false);
|
|
19643
21434
|
isFooterFrameSelectionRef.current = isFooterFrameSelection;
|
|
19644
|
-
const [floatingPanel, setFloatingPanel] = (0, import_react19.useState)(null);
|
|
19645
|
-
const floatingPanelOpenRef = (0, import_react19.useRef)(false);
|
|
19646
|
-
floatingPanelOpenRef.current = floatingPanel !== null;
|
|
19647
|
-
const [floatingPanelPos, setFloatingPanelPos] = (0, import_react19.useState)(null);
|
|
19648
|
-
const [logoSizeDraft, setLogoSizeDraft] = (0, import_react19.useState)(null);
|
|
19649
|
-
const [editorViewport, setEditorViewport] = (0, import_react19.useState)("desktop");
|
|
19650
|
-
const [parentScrollSnap, setParentScrollSnap] = (0, import_react19.useState)(null);
|
|
19651
21435
|
const [navDropdownPreviewOpen, setNavDropdownPreviewOpen] = (0, import_react19.useState)(null);
|
|
19652
21436
|
const [footerHeadingVisible, setFooterHeadingVisible] = (0, import_react19.useState)(null);
|
|
19653
21437
|
const footerDragRef = (0, import_react19.useRef)(null);
|
|
@@ -19671,6 +21455,21 @@ function OhhwellsBridge() {
|
|
|
19671
21455
|
const stylesRef = (0, import_react19.useRef)("");
|
|
19672
21456
|
const appliedDrawerRef = (0, import_react19.useRef)(null);
|
|
19673
21457
|
const pendingDeleteUndoRef = (0, import_react19.useRef)(null);
|
|
21458
|
+
const [floatingPanel, setFloatingPanel] = (0, import_react19.useState)(null);
|
|
21459
|
+
const floatingPanelOpenRef = (0, import_react19.useRef)(false);
|
|
21460
|
+
const floatingPanelRef = (0, import_react19.useRef)(null);
|
|
21461
|
+
floatingPanelRef.current = floatingPanel;
|
|
21462
|
+
const setFloatingPanelRef = (0, import_react19.useRef)(setFloatingPanel);
|
|
21463
|
+
const [floatingPanelPos, setFloatingPanelPos] = (0, import_react19.useState)(null);
|
|
21464
|
+
const buttonCollectionDragRef = (0, import_react19.useRef)(null);
|
|
21465
|
+
const buttonDropInsertIndexRef = (0, import_react19.useRef)(null);
|
|
21466
|
+
const [buttonDropSlots, setButtonDropSlots] = (0, import_react19.useState)([]);
|
|
21467
|
+
const [activeButtonDropIndex, setActiveButtonDropIndex] = (0, import_react19.useState)(null);
|
|
21468
|
+
const buttonPointerDragRef = (0, import_react19.useRef)(null);
|
|
21469
|
+
const [buttonStyleTick, setButtonStyleTick] = (0, import_react19.useState)(0);
|
|
21470
|
+
const [logoSizeDraft, setLogoSizeDraft] = (0, import_react19.useState)(null);
|
|
21471
|
+
const [editorViewport, setEditorViewport] = (0, import_react19.useState)("desktop");
|
|
21472
|
+
const [parentScrollSnap, setParentScrollSnap] = (0, import_react19.useState)(null);
|
|
19674
21473
|
const [sitePages, setSitePages] = (0, import_react19.useState)([]);
|
|
19675
21474
|
const [sectionsByPath, setSectionsByPath] = (0, import_react19.useState)({});
|
|
19676
21475
|
const sectionsPrefetchGenRef = (0, import_react19.useRef)(0);
|
|
@@ -19679,7 +21478,18 @@ function OhhwellsBridge() {
|
|
|
19679
21478
|
const linkPopoverOpenRef = (0, import_react19.useRef)(false);
|
|
19680
21479
|
const linkPopoverGraceUntilRef = (0, import_react19.useRef)(0);
|
|
19681
21480
|
setLinkPopoverRef.current = setLinkPopover;
|
|
21481
|
+
setFloatingPanelRef.current = setFloatingPanel;
|
|
19682
21482
|
linkPopoverSessionRef.current = linkPopover;
|
|
21483
|
+
floatingPanelOpenRef.current = Boolean(floatingPanel);
|
|
21484
|
+
(0, import_react19.useEffect)(() => {
|
|
21485
|
+
const syncViewport = () => {
|
|
21486
|
+
const next = window.innerWidth <= 480 ? "mobile" : "desktop";
|
|
21487
|
+
setEditorViewport((prev) => prev === next ? prev : next);
|
|
21488
|
+
};
|
|
21489
|
+
syncViewport();
|
|
21490
|
+
window.addEventListener("resize", syncViewport);
|
|
21491
|
+
return () => window.removeEventListener("resize", syncViewport);
|
|
21492
|
+
}, []);
|
|
19683
21493
|
(0, import_react19.useEffect)(() => {
|
|
19684
21494
|
setSectionOrderPersistHandler((entries) => {
|
|
19685
21495
|
const currentPath = window.location.pathname;
|
|
@@ -19945,6 +21755,7 @@ function OhhwellsBridge() {
|
|
|
19945
21755
|
hoveredItemElRef.current = null;
|
|
19946
21756
|
setHoveredItemRect(null);
|
|
19947
21757
|
setFloatingPanel(null);
|
|
21758
|
+
setFloatingPanelPos(null);
|
|
19948
21759
|
setLogoSizeDraft(null);
|
|
19949
21760
|
if (!activeElRef.current) {
|
|
19950
21761
|
if (nestedGroup?.isConnected) {
|
|
@@ -20545,6 +22356,47 @@ function OhhwellsBridge() {
|
|
|
20545
22356
|
},
|
|
20546
22357
|
[beginFooterDrag]
|
|
20547
22358
|
);
|
|
22359
|
+
const persistButtonCollectionDrag = (0, import_react19.useCallback)(
|
|
22360
|
+
(button, clientX) => {
|
|
22361
|
+
const insertIndex = buttonDropInsertIndexRef.current;
|
|
22362
|
+
if (insertIndex != null) insertButtonAtCollectionIndex(button, insertIndex);
|
|
22363
|
+
else if (typeof clientX === "number" && clientX !== 0) reorderButtonInCollection(button, clientX);
|
|
22364
|
+
buttonDropInsertIndexRef.current = null;
|
|
22365
|
+
const collection = buttonCollectionOf(button);
|
|
22366
|
+
if (collection) {
|
|
22367
|
+
const persisted = persistCollectionOrder(collection, editContentRef.current);
|
|
22368
|
+
if (persisted) {
|
|
22369
|
+
editContentRef.current = persisted.content;
|
|
22370
|
+
postToParent2({ type: "ow:change", nodes: persisted.nodes });
|
|
22371
|
+
}
|
|
22372
|
+
}
|
|
22373
|
+
buttonCollectionDragRef.current = null;
|
|
22374
|
+
buttonPointerDragRef.current = null;
|
|
22375
|
+
setButtonDropSlots([]);
|
|
22376
|
+
setActiveButtonDropIndex(null);
|
|
22377
|
+
setIsItemDragging(false);
|
|
22378
|
+
unlockFooterDragInteraction();
|
|
22379
|
+
if (button.isConnected) setToolbarRect(button.getBoundingClientRect());
|
|
22380
|
+
},
|
|
22381
|
+
[postToParent2]
|
|
22382
|
+
);
|
|
22383
|
+
const refreshButtonDragVisuals = (0, import_react19.useCallback)((button, clientX, clientY) => {
|
|
22384
|
+
const collection = buttonCollectionOf(button);
|
|
22385
|
+
if (!collection) {
|
|
22386
|
+
setButtonDropSlots([]);
|
|
22387
|
+
setActiveButtonDropIndex(null);
|
|
22388
|
+
buttonDropInsertIndexRef.current = null;
|
|
22389
|
+
return;
|
|
22390
|
+
}
|
|
22391
|
+
const slots = buildButtonCollectionDropSlots(collection);
|
|
22392
|
+
const active = hitTestButtonCollectionDropSlot(collection, clientX, clientY);
|
|
22393
|
+
setButtonDropSlots(slots);
|
|
22394
|
+
const idx = active ? slots.findIndex((slot) => slot.insertIndex === active.insertIndex) : -1;
|
|
22395
|
+
setActiveButtonDropIndex(idx >= 0 ? idx : null);
|
|
22396
|
+
buttonDropInsertIndexRef.current = active?.insertIndex ?? null;
|
|
22397
|
+
setDraggedItemRect(button.getBoundingClientRect());
|
|
22398
|
+
if (selectedElRef.current === button) setToolbarRect(button.getBoundingClientRect());
|
|
22399
|
+
}, []);
|
|
20548
22400
|
const handleItemDragStart = (0, import_react19.useCallback)(
|
|
20549
22401
|
(e) => {
|
|
20550
22402
|
const selected = selectedElRef.current;
|
|
@@ -20554,6 +22406,17 @@ function OhhwellsBridge() {
|
|
|
20554
22406
|
}
|
|
20555
22407
|
const clientX = e?.clientX ?? selected.getBoundingClientRect().left + 8;
|
|
20556
22408
|
const clientY = e?.clientY ?? selected.getBoundingClientRect().top + 8;
|
|
22409
|
+
if (isCtaButton(selected) && collectionDragEnabled(selected)) {
|
|
22410
|
+
buttonCollectionDragRef.current = selected;
|
|
22411
|
+
setMediaHover(null);
|
|
22412
|
+
if (e?.dataTransfer) {
|
|
22413
|
+
e.dataTransfer.effectAllowed = "move";
|
|
22414
|
+
e.dataTransfer.setData("text/plain", buttonId(selected) ?? "button");
|
|
22415
|
+
}
|
|
22416
|
+
setIsItemDragging(true);
|
|
22417
|
+
refreshButtonDragVisuals(selected, clientX, clientY);
|
|
22418
|
+
return;
|
|
22419
|
+
}
|
|
20557
22420
|
if (startFooterLinkDrag(selected, clientX, clientY, true)) return;
|
|
20558
22421
|
if (selected.hasAttribute("data-ohw-footer-col") || isInferredFooterGroup2(selected) && selected.closest("footer")) {
|
|
20559
22422
|
if (startFooterColumnDrag(selected, clientX, clientY, true)) return;
|
|
@@ -20563,10 +22426,15 @@ function OhhwellsBridge() {
|
|
|
20563
22426
|
setSiblingHintRect(null);
|
|
20564
22427
|
setIsItemDragging(true);
|
|
20565
22428
|
},
|
|
20566
|
-
[startFooterColumnDrag, startFooterLinkDrag, startNavLinkDrag]
|
|
22429
|
+
[startFooterColumnDrag, startFooterLinkDrag, startNavLinkDrag, refreshButtonDragVisuals]
|
|
20567
22430
|
);
|
|
20568
22431
|
const handleItemDragEnd = (0, import_react19.useCallback)(
|
|
20569
22432
|
(e) => {
|
|
22433
|
+
const collectionButton = buttonCollectionDragRef.current;
|
|
22434
|
+
if (collectionButton) {
|
|
22435
|
+
persistButtonCollectionDrag(collectionButton, e?.clientX);
|
|
22436
|
+
return;
|
|
22437
|
+
}
|
|
20570
22438
|
if (footerDragRef.current) {
|
|
20571
22439
|
const x = e?.clientX;
|
|
20572
22440
|
const y = e?.clientY;
|
|
@@ -20589,12 +22457,22 @@ function OhhwellsBridge() {
|
|
|
20589
22457
|
}
|
|
20590
22458
|
setIsItemDragging(false);
|
|
20591
22459
|
},
|
|
20592
|
-
[commitFooterDrag, commitNavDrag, navDragRef]
|
|
22460
|
+
[commitFooterDrag, commitNavDrag, navDragRef, persistButtonCollectionDrag]
|
|
20593
22461
|
);
|
|
20594
22462
|
const handleItemChromePointerDown = (0, import_react19.useCallback)((e) => {
|
|
20595
22463
|
if (e.button !== 0) return;
|
|
20596
22464
|
const selected = selectedElRef.current;
|
|
20597
22465
|
if (!selected) return;
|
|
22466
|
+
if (isCtaButton(selected) && collectionDragEnabled(selected)) {
|
|
22467
|
+
buttonPointerDragRef.current = {
|
|
22468
|
+
el: selected,
|
|
22469
|
+
startX: e.clientX,
|
|
22470
|
+
startY: e.clientY,
|
|
22471
|
+
pointerId: e.pointerId,
|
|
22472
|
+
started: false
|
|
22473
|
+
};
|
|
22474
|
+
return;
|
|
22475
|
+
}
|
|
20598
22476
|
const hrefKey = selected.getAttribute("data-ohw-href-key");
|
|
20599
22477
|
if (hrefKey && isFooterHrefKey(hrefKey)) {
|
|
20600
22478
|
footerPointerDragRef.current = {
|
|
@@ -20673,10 +22551,29 @@ function OhhwellsBridge() {
|
|
|
20673
22551
|
setIsFooterFrameSelection(false);
|
|
20674
22552
|
setToolbarVariant("link-action");
|
|
20675
22553
|
setToolbarRect(anchor.getBoundingClientRect());
|
|
22554
|
+
if (glowElRef.current) glowElRef.current.style.display = "";
|
|
20676
22555
|
setToolbarShowEditLink(false);
|
|
20677
22556
|
setActiveCommands(/* @__PURE__ */ new Set());
|
|
20678
|
-
|
|
20679
|
-
|
|
22557
|
+
const panel = floatingPanelRef.current;
|
|
22558
|
+
if (panel?.kind === "button-style" && isCtaButton(anchor)) {
|
|
22559
|
+
const id = buttonId(anchor);
|
|
22560
|
+
if (id && panel.buttonId !== id) {
|
|
22561
|
+
captureButtonOrigin(anchor);
|
|
22562
|
+
setFloatingPanelPos(null);
|
|
22563
|
+
setParentScrollSnap(parentScrollRef.current);
|
|
22564
|
+
setFloatingPanel({
|
|
22565
|
+
...panel,
|
|
22566
|
+
key: `button-style:${id}`,
|
|
22567
|
+
buttonId: id,
|
|
22568
|
+
context: buttonStyleContext(anchor)
|
|
22569
|
+
});
|
|
22570
|
+
setButtonStyleTick((n) => n + 1);
|
|
22571
|
+
}
|
|
22572
|
+
} else {
|
|
22573
|
+
setFloatingPanel(null);
|
|
22574
|
+
setFloatingPanelPos(null);
|
|
22575
|
+
setLogoSizeDraft(null);
|
|
22576
|
+
}
|
|
20680
22577
|
}, [deactivate, markSelected]);
|
|
20681
22578
|
const selectFrame = (0, import_react19.useCallback)((el) => {
|
|
20682
22579
|
if (!isNavigationContainer(el)) return;
|
|
@@ -20716,6 +22613,7 @@ function OhhwellsBridge() {
|
|
|
20716
22613
|
setToolbarShowEditLink(false);
|
|
20717
22614
|
setActiveCommands(/* @__PURE__ */ new Set());
|
|
20718
22615
|
setFloatingPanel(null);
|
|
22616
|
+
setFloatingPanelPos(null);
|
|
20719
22617
|
setLogoSizeDraft(null);
|
|
20720
22618
|
}, [deactivate, markSelected, postToParent2]);
|
|
20721
22619
|
const selectLogo = (0, import_react19.useCallback)(
|
|
@@ -20761,6 +22659,7 @@ function OhhwellsBridge() {
|
|
|
20761
22659
|
});
|
|
20762
22660
|
}, []);
|
|
20763
22661
|
const openSocialsDisplayPanel = (0, import_react19.useCallback)((row) => {
|
|
22662
|
+
setFloatingPanelPos(null);
|
|
20764
22663
|
setParentScrollSnap(parentScrollRef.current);
|
|
20765
22664
|
setFloatingPanel({
|
|
20766
22665
|
key: "socials-display",
|
|
@@ -20770,6 +22669,87 @@ function OhhwellsBridge() {
|
|
|
20770
22669
|
row
|
|
20771
22670
|
});
|
|
20772
22671
|
}, []);
|
|
22672
|
+
const rememberButtonTokens = (0, import_react19.useCallback)(
|
|
22673
|
+
(content, tokens, nodes) => {
|
|
22674
|
+
if (nodes.length === 0) return content;
|
|
22675
|
+
const next = { ...content };
|
|
22676
|
+
for (const node of nodes) next[node.key] = node.text;
|
|
22677
|
+
editContentRef.current = next;
|
|
22678
|
+
postToParent2({ type: "ow:change", nodes });
|
|
22679
|
+
return next;
|
|
22680
|
+
},
|
|
22681
|
+
[postToParent2]
|
|
22682
|
+
);
|
|
22683
|
+
const tokensForButton = (0, import_react19.useCallback)(
|
|
22684
|
+
(el, persistFallback = false) => {
|
|
22685
|
+
const stored = readStoredStyleTokens(editContentRef.current);
|
|
22686
|
+
if (stored) return stored;
|
|
22687
|
+
const ensured = ensureButtonStyleTokens(document, editContentRef.current);
|
|
22688
|
+
if (ensured.tokens) {
|
|
22689
|
+
rememberButtonTokens(editContentRef.current, ensured.tokens, ensured.nodes);
|
|
22690
|
+
return ensured.tokens;
|
|
22691
|
+
}
|
|
22692
|
+
const fallback = tokensFromButton(el);
|
|
22693
|
+
if (persistFallback) rememberButtonTokens(editContentRef.current, fallback, styleTokenNodes(fallback));
|
|
22694
|
+
return fallback;
|
|
22695
|
+
},
|
|
22696
|
+
[rememberButtonTokens]
|
|
22697
|
+
);
|
|
22698
|
+
const openButtonStylePanel = (0, import_react19.useCallback)(
|
|
22699
|
+
(anchor) => {
|
|
22700
|
+
const id = buttonId(anchor);
|
|
22701
|
+
if (!id) return;
|
|
22702
|
+
captureButtonOrigin(anchor);
|
|
22703
|
+
tokensForButton(anchor);
|
|
22704
|
+
setFloatingPanelPos(null);
|
|
22705
|
+
setParentScrollSnap(parentScrollRef.current);
|
|
22706
|
+
setFloatingPanel({
|
|
22707
|
+
key: `button-style:${id}`,
|
|
22708
|
+
title: "Style",
|
|
22709
|
+
context: buttonStyleContext(anchor),
|
|
22710
|
+
kind: "button-style",
|
|
22711
|
+
buttonId: id
|
|
22712
|
+
});
|
|
22713
|
+
},
|
|
22714
|
+
[tokensForButton]
|
|
22715
|
+
);
|
|
22716
|
+
const applySelectedButtonStyle = (0, import_react19.useCallback)(
|
|
22717
|
+
(patch) => {
|
|
22718
|
+
const panel = floatingPanelRef.current;
|
|
22719
|
+
const id = panel?.kind === "button-style" ? panel.buttonId : null;
|
|
22720
|
+
const el = id ? document.querySelector(`[data-ohw-href-key="${CSS.escape(id)}"]`) : null;
|
|
22721
|
+
if (!el || !id || !isCtaButton(el)) return;
|
|
22722
|
+
const tokens = tokensFromButton(el);
|
|
22723
|
+
const next = { ...assignmentFor(el, editContentRef.current, tokens), ...patch };
|
|
22724
|
+
const assignments = withAssignment(editContentRef.current, id, next);
|
|
22725
|
+
const text = JSON.stringify(assignments);
|
|
22726
|
+
editContentRef.current = { ...editContentRef.current, [BUTTON_ASSIGNMENTS_KEY]: text };
|
|
22727
|
+
applyButtonStyle(el, next, tokens);
|
|
22728
|
+
postToParent2({ type: "ow:change", nodes: [{ key: BUTTON_ASSIGNMENTS_KEY, text }] });
|
|
22729
|
+
setButtonStyleTick((n) => n + 1);
|
|
22730
|
+
if (selectedElRef.current === el) setToolbarRect(el.getBoundingClientRect());
|
|
22731
|
+
},
|
|
22732
|
+
[postToParent2]
|
|
22733
|
+
);
|
|
22734
|
+
(0, import_react19.useEffect)(() => {
|
|
22735
|
+
const onDragOver = (e) => {
|
|
22736
|
+
const dragged = buttonCollectionDragRef.current;
|
|
22737
|
+
if (!dragged) return;
|
|
22738
|
+
e.preventDefault();
|
|
22739
|
+
if (e.dataTransfer) e.dataTransfer.dropEffect = "move";
|
|
22740
|
+
refreshButtonDragVisuals(dragged, e.clientX, e.clientY);
|
|
22741
|
+
};
|
|
22742
|
+
const onDrop = (e) => {
|
|
22743
|
+
if (!buttonCollectionDragRef.current) return;
|
|
22744
|
+
e.preventDefault();
|
|
22745
|
+
};
|
|
22746
|
+
document.addEventListener("dragover", onDragOver);
|
|
22747
|
+
document.addEventListener("drop", onDrop);
|
|
22748
|
+
return () => {
|
|
22749
|
+
document.removeEventListener("dragover", onDragOver);
|
|
22750
|
+
document.removeEventListener("drop", onDrop);
|
|
22751
|
+
};
|
|
22752
|
+
}, [refreshButtonDragVisuals]);
|
|
20773
22753
|
const isEditModeRef = (0, import_react19.useRef)(false);
|
|
20774
22754
|
const requestMissingSocialIconsRef = (0, import_react19.useRef)(() => {
|
|
20775
22755
|
});
|
|
@@ -20812,11 +22792,13 @@ function OhhwellsBridge() {
|
|
|
20812
22792
|
);
|
|
20813
22793
|
const closeFloatingPanelOnly = (0, import_react19.useCallback)(() => {
|
|
20814
22794
|
setFloatingPanel(null);
|
|
22795
|
+
setFloatingPanelPos(null);
|
|
20815
22796
|
setLogoSizeDraft(null);
|
|
20816
22797
|
}, []);
|
|
20817
22798
|
closeFloatingPanelOnlyRef.current = closeFloatingPanelOnly;
|
|
20818
22799
|
const closeFloatingPanelAndDeselect = (0, import_react19.useCallback)(() => {
|
|
20819
22800
|
setFloatingPanel(null);
|
|
22801
|
+
setFloatingPanelPos(null);
|
|
20820
22802
|
setLogoSizeDraft(null);
|
|
20821
22803
|
deselectRef.current();
|
|
20822
22804
|
}, []);
|
|
@@ -21025,6 +23007,7 @@ function OhhwellsBridge() {
|
|
|
21025
23007
|
}
|
|
21026
23008
|
if (typeof content[STYLE_STORE_KEY] === "string") {
|
|
21027
23009
|
stylesRef.current = content[STYLE_STORE_KEY];
|
|
23010
|
+
document.querySelectorAll('[data-ohw-editable="form"]').forEach((f) => markFormFields(f));
|
|
21028
23011
|
applyStylesToDom(parseStyleStore(content[STYLE_STORE_KEY]));
|
|
21029
23012
|
}
|
|
21030
23013
|
applyBrandChrome(content);
|
|
@@ -21033,12 +23016,12 @@ function OhhwellsBridge() {
|
|
|
21033
23016
|
for (const [key, val] of Object.entries(content)) {
|
|
21034
23017
|
if (key === "__ohw_sections") continue;
|
|
21035
23018
|
if (key === AI_SECTIONS_KEY) continue;
|
|
23019
|
+
if (key === LOGO_PLACEHOLDER_KEY) continue;
|
|
23020
|
+
if (LOGO_IMAGE_KEYS.includes(key)) continue;
|
|
21036
23021
|
if (key === BRAND_KIT_KEY) continue;
|
|
21037
23022
|
if (key === STYLE_STORE_KEY) continue;
|
|
21038
23023
|
if (BRAND_CHROME_KEYS.has(key)) continue;
|
|
21039
|
-
if (key === LOGO_PLACEHOLDER_KEY) continue;
|
|
21040
23024
|
if (key === CUSTOM_CODE_AFTER_HEAD_KEY || key === CUSTOM_CODE_BEFORE_HEAD_KEY) continue;
|
|
21041
|
-
if (LOGO_IMAGE_KEYS.includes(key)) continue;
|
|
21042
23025
|
if (applyVideoSettingNode(key, val)) continue;
|
|
21043
23026
|
if (applyCarouselNode(key, val)) continue;
|
|
21044
23027
|
document.querySelectorAll(`[data-ohw-key="${key}"]`).forEach((el) => {
|
|
@@ -21085,6 +23068,7 @@ function OhhwellsBridge() {
|
|
|
21085
23068
|
reconcileSocialsFromContent(content);
|
|
21086
23069
|
applySocialsDisplayFromContent(content);
|
|
21087
23070
|
applySocialsLabelsFromContent(content, document, { fillEmptyOnly: isEditModeRef.current });
|
|
23071
|
+
syncButtonsFromContent(document, content);
|
|
21088
23072
|
if (isEditModeRef.current) requestMissingSocialIconsRef.current();
|
|
21089
23073
|
if (typeof content[STYLE_STORE_KEY] === "string") {
|
|
21090
23074
|
applyStylesToDom(parseStyleStore(content[STYLE_STORE_KEY]));
|
|
@@ -21109,7 +23093,9 @@ function OhhwellsBridge() {
|
|
|
21109
23093
|
let cancelled = false;
|
|
21110
23094
|
setFetchState("loading");
|
|
21111
23095
|
const apiUrl = process.env.NEXT_PUBLIC_FLOWOPS_API_URL ?? "https://flowops-backend-staging-2yfdh7pwpq-as.a.run.app";
|
|
21112
|
-
|
|
23096
|
+
const initialPath = pathname;
|
|
23097
|
+
fetchedContentPaths.add(`${subdomain}::${initialPath}`);
|
|
23098
|
+
fetch(`${apiUrl}/api/public/sites/${subdomain}/content?path=${encodeURIComponent(initialPath)}`, { cache: "no-store" }).then((r2) => r2.ok ? r2.json() : null).then((data) => {
|
|
21113
23099
|
if (cancelled) return;
|
|
21114
23100
|
const content = data?.content ?? {};
|
|
21115
23101
|
const branding = Boolean(data?.showBranding);
|
|
@@ -21245,16 +23231,17 @@ function OhhwellsBridge() {
|
|
|
21245
23231
|
applyAiSectionsToDom(parseAiSectionsState(content[AI_SECTIONS_KEY]));
|
|
21246
23232
|
}
|
|
21247
23233
|
if (typeof content[STYLE_STORE_KEY] === "string") {
|
|
23234
|
+
document.querySelectorAll('[data-ohw-editable="form"]').forEach((f) => markFormFields(f));
|
|
21248
23235
|
applyStylesToDom(parseStyleStore(content[STYLE_STORE_KEY]));
|
|
21249
23236
|
}
|
|
21250
23237
|
for (const [key, val] of Object.entries(content)) {
|
|
21251
23238
|
if (key === "__ohw_sections") continue;
|
|
21252
23239
|
if (key === AI_SECTIONS_KEY) continue;
|
|
23240
|
+
if (key === LOGO_PLACEHOLDER_KEY) continue;
|
|
23241
|
+
if (LOGO_IMAGE_KEYS.includes(key)) continue;
|
|
21253
23242
|
if (key === BRAND_KIT_KEY) continue;
|
|
21254
23243
|
if (key === STYLE_STORE_KEY) continue;
|
|
21255
23244
|
if (BRAND_CHROME_KEYS.has(key)) continue;
|
|
21256
|
-
if (key === LOGO_PLACEHOLDER_KEY) continue;
|
|
21257
|
-
if (LOGO_IMAGE_KEYS.includes(key)) continue;
|
|
21258
23245
|
if (applyVideoSettingNode(key, val)) continue;
|
|
21259
23246
|
if (applyCarouselNode(key, val)) continue;
|
|
21260
23247
|
document.querySelectorAll(`[data-ohw-key="${key}"]`).forEach((el) => {
|
|
@@ -21285,6 +23272,7 @@ function OhhwellsBridge() {
|
|
|
21285
23272
|
reconcileSocialsFromContent(content);
|
|
21286
23273
|
applySocialsDisplayFromContent(content);
|
|
21287
23274
|
applySocialsLabelsFromContent(content, document, { fillEmptyOnly: isEditModeRef.current });
|
|
23275
|
+
syncButtonsFromContent(document, content);
|
|
21288
23276
|
if (isEditModeRef.current) requestMissingSocialIconsRef.current();
|
|
21289
23277
|
if (typeof content[STYLE_STORE_KEY] === "string") {
|
|
21290
23278
|
applyStylesToDom(parseStyleStore(content[STYLE_STORE_KEY]));
|
|
@@ -21305,6 +23293,17 @@ function OhhwellsBridge() {
|
|
|
21305
23293
|
debounceTimer = setTimeout(applyFromCache, 150);
|
|
21306
23294
|
};
|
|
21307
23295
|
applyFromCache();
|
|
23296
|
+
const pathCacheKey = `${subdomain}::${pathname}`;
|
|
23297
|
+
if (!fetchedContentPaths.has(pathCacheKey)) {
|
|
23298
|
+
fetchedContentPaths.add(pathCacheKey);
|
|
23299
|
+
const apiUrl = process.env.NEXT_PUBLIC_FLOWOPS_API_URL ?? "https://flowops-backend-staging-2yfdh7pwpq-as.a.run.app";
|
|
23300
|
+
fetch(`${apiUrl}/api/public/sites/${subdomain}/content?path=${encodeURIComponent(pathname)}`, { cache: "no-store" }).then((r2) => r2.ok ? r2.json() : null).then((data) => {
|
|
23301
|
+
if (!data?.content) return;
|
|
23302
|
+
contentCache.set(subdomain, data.content);
|
|
23303
|
+
applyFromCache();
|
|
23304
|
+
}).catch(() => {
|
|
23305
|
+
});
|
|
23306
|
+
}
|
|
21308
23307
|
observer = new MutationObserver(scheduleApply);
|
|
21309
23308
|
observer.observe(document.body, { childList: true, subtree: true });
|
|
21310
23309
|
return () => {
|
|
@@ -21373,7 +23372,10 @@ function OhhwellsBridge() {
|
|
|
21373
23372
|
if (roots.length === 0) {
|
|
21374
23373
|
reconcileNavbarItemsFromContent(contentForNav());
|
|
21375
23374
|
reconcileFooterOrderFromContent(contentForNav());
|
|
21376
|
-
if (isEditMode)
|
|
23375
|
+
if (isEditMode) {
|
|
23376
|
+
syncButtonsFromContent(document, contentForNav());
|
|
23377
|
+
syncNavigationDragCursorAttrs();
|
|
23378
|
+
}
|
|
21377
23379
|
return;
|
|
21378
23380
|
}
|
|
21379
23381
|
let rafId = null;
|
|
@@ -21385,7 +23387,7 @@ function OhhwellsBridge() {
|
|
|
21385
23387
|
}
|
|
21386
23388
|
};
|
|
21387
23389
|
const run = () => {
|
|
21388
|
-
if (footerDragRef.current || navDragRef.current || applying) return;
|
|
23390
|
+
if (footerDragRef.current || navDragRef.current || buttonCollectionDragRef.current || applying) return;
|
|
21389
23391
|
applying = true;
|
|
21390
23392
|
observer?.disconnect();
|
|
21391
23393
|
try {
|
|
@@ -21395,6 +23397,7 @@ function OhhwellsBridge() {
|
|
|
21395
23397
|
reconcileSocialsFromContent(content);
|
|
21396
23398
|
applySocialsDisplayFromContent(content);
|
|
21397
23399
|
applySocialsLabelsFromContent(content, document, { fillEmptyOnly: isEditModeRef.current });
|
|
23400
|
+
syncButtonsFromContent(document, content);
|
|
21398
23401
|
if (isEditModeRef.current) requestMissingSocialIconsRef.current();
|
|
21399
23402
|
document.querySelectorAll("footer [data-ohw-href-key]").forEach((el) => {
|
|
21400
23403
|
if (isFooterHrefKey(el.getAttribute("data-ohw-href-key")) || getSocialItem(el)) {
|
|
@@ -21402,9 +23405,9 @@ function OhhwellsBridge() {
|
|
|
21402
23405
|
}
|
|
21403
23406
|
});
|
|
21404
23407
|
document.querySelectorAll(
|
|
21405
|
-
|
|
23408
|
+
'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"]'
|
|
21406
23409
|
).forEach((el) => {
|
|
21407
|
-
if (isNavbarHrefKey(el.getAttribute("data-ohw-href-key"))) {
|
|
23410
|
+
if (isNavbarHrefKey(el.getAttribute("data-ohw-href-key")) || isCtaButton(el)) {
|
|
21408
23411
|
disableNativeHrefDrag(el);
|
|
21409
23412
|
}
|
|
21410
23413
|
});
|
|
@@ -21429,6 +23432,44 @@ function OhhwellsBridge() {
|
|
|
21429
23432
|
observer?.disconnect();
|
|
21430
23433
|
};
|
|
21431
23434
|
}, [isEditMode, pathname, subdomain, fetchState, resyncSelectedNavigationItem]);
|
|
23435
|
+
(0, import_react19.useEffect)(() => {
|
|
23436
|
+
if (!isEditMode) return;
|
|
23437
|
+
let applying = false;
|
|
23438
|
+
let rafId = null;
|
|
23439
|
+
const run = () => {
|
|
23440
|
+
if (applying || buttonCollectionDragRef.current) return;
|
|
23441
|
+
const content = editContentRef.current;
|
|
23442
|
+
if (!content[BUTTON_COLLECTIONS_KEY] && !content[BUTTON_SNAPSHOTS_KEY]) return;
|
|
23443
|
+
applying = true;
|
|
23444
|
+
try {
|
|
23445
|
+
syncButtonsFromContent(document, content);
|
|
23446
|
+
} finally {
|
|
23447
|
+
applying = false;
|
|
23448
|
+
}
|
|
23449
|
+
};
|
|
23450
|
+
const schedule = () => {
|
|
23451
|
+
if (rafId != null) return;
|
|
23452
|
+
rafId = requestAnimationFrame(() => {
|
|
23453
|
+
rafId = null;
|
|
23454
|
+
run();
|
|
23455
|
+
});
|
|
23456
|
+
};
|
|
23457
|
+
const observer = new MutationObserver((mutations) => {
|
|
23458
|
+
if (mutations.every((m) => {
|
|
23459
|
+
const t = m.target;
|
|
23460
|
+
return t instanceof Element && Boolean(t.closest("[data-ohw-bridge], [data-ohw-bridge-root], [data-ohw-button-collection]"));
|
|
23461
|
+
})) {
|
|
23462
|
+
return;
|
|
23463
|
+
}
|
|
23464
|
+
schedule();
|
|
23465
|
+
});
|
|
23466
|
+
observer.observe(document.body, { childList: true, subtree: true });
|
|
23467
|
+
run();
|
|
23468
|
+
return () => {
|
|
23469
|
+
if (rafId != null) cancelAnimationFrame(rafId);
|
|
23470
|
+
observer.disconnect();
|
|
23471
|
+
};
|
|
23472
|
+
}, [isEditMode, pathname]);
|
|
21432
23473
|
(0, import_react19.useEffect)(() => {
|
|
21433
23474
|
if (!isEditMode) return;
|
|
21434
23475
|
let lastPosted = 0;
|
|
@@ -21451,26 +23492,11 @@ function OhhwellsBridge() {
|
|
|
21451
23492
|
const t2 = setTimeout(measure, 500);
|
|
21452
23493
|
const ro = new ResizeObserver(schedule);
|
|
21453
23494
|
ro.observe(document.body);
|
|
21454
|
-
let lastWidth = window.innerWidth;
|
|
21455
|
-
let resizeTimers = [];
|
|
21456
|
-
const clearResizeTimers = () => {
|
|
21457
|
-
resizeTimers.forEach(clearTimeout);
|
|
21458
|
-
resizeTimers = [];
|
|
21459
|
-
};
|
|
21460
|
-
const handleResize = () => {
|
|
21461
|
-
if (window.innerWidth === lastWidth) return;
|
|
21462
|
-
lastWidth = window.innerWidth;
|
|
21463
|
-
clearResizeTimers();
|
|
21464
|
-
resizeTimers = HEIGHT_SETTLE_DELAYS.map((delay) => setTimeout(measure, delay));
|
|
21465
|
-
};
|
|
21466
|
-
window.addEventListener("resize", handleResize);
|
|
21467
23495
|
return () => {
|
|
21468
23496
|
clearTimeout(t1);
|
|
21469
23497
|
clearTimeout(t2);
|
|
21470
23498
|
if (raf != null) cancelAnimationFrame(raf);
|
|
21471
23499
|
ro.disconnect();
|
|
21472
|
-
clearResizeTimers();
|
|
21473
|
-
window.removeEventListener("resize", handleResize);
|
|
21474
23500
|
};
|
|
21475
23501
|
}, [pathname, isEditMode, postToParent2]);
|
|
21476
23502
|
(0, import_react19.useEffect)(() => {
|
|
@@ -21765,6 +23791,13 @@ function OhhwellsBridge() {
|
|
|
21765
23791
|
if (target.closest("[data-ohw-state-toggle]")) return;
|
|
21766
23792
|
if (target.closest("[data-ohw-max-badge]")) return;
|
|
21767
23793
|
if (isInsideLinkEditor(target)) return;
|
|
23794
|
+
if (isInsideFloatingPanel(target)) return;
|
|
23795
|
+
if (target.closest("[data-ohw-form-toolbar]")) return;
|
|
23796
|
+
if (target.closest(
|
|
23797
|
+
'[data-ohw-field-toolbar], [data-ohw-field-type-picker], [data-radix-popper-content-wrapper], [role="menu"], [data-slot="dropdown-menu-content"]'
|
|
23798
|
+
)) {
|
|
23799
|
+
return;
|
|
23800
|
+
}
|
|
21768
23801
|
if (selectedMediaElRef.current && !selectedMediaElRef.current.contains(target) && !target.closest("[data-ohw-media-overlay], [data-ohw-edit-chrome], [data-ohw-item-interaction]")) {
|
|
21769
23802
|
clearMediaSelectionRef.current();
|
|
21770
23803
|
}
|
|
@@ -21785,13 +23818,6 @@ function OhhwellsBridge() {
|
|
|
21785
23818
|
return;
|
|
21786
23819
|
}
|
|
21787
23820
|
}
|
|
21788
|
-
if (isInsideFloatingPanel(target)) return;
|
|
21789
|
-
if (target.closest("[data-ohw-form-toolbar]")) return;
|
|
21790
|
-
if (target.closest(
|
|
21791
|
-
'[data-ohw-field-toolbar], [data-ohw-field-type-picker], [data-radix-popper-content-wrapper], [role="menu"], [data-slot="dropdown-menu-content"]'
|
|
21792
|
-
)) {
|
|
21793
|
-
return;
|
|
21794
|
-
}
|
|
21795
23821
|
{
|
|
21796
23822
|
const formEl = getFormElement(target);
|
|
21797
23823
|
const onSuccessText = target.closest(`[${SUCCESS_TEXT_ATTR}]`);
|
|
@@ -21955,14 +23981,6 @@ function OhhwellsBridge() {
|
|
|
21955
23981
|
}
|
|
21956
23982
|
const clickedButton = findClosestButtonLike(target);
|
|
21957
23983
|
const buttonOnMedia = Boolean(clickedButton && isMediaEditable(editable) && editable.contains(clickedButton));
|
|
21958
|
-
console.log("[click-debug]", {
|
|
21959
|
-
editableType: editable.dataset.ohwEditable,
|
|
21960
|
-
editableTag: editable.tagName,
|
|
21961
|
-
targetTag: target.tagName,
|
|
21962
|
-
clickedButtonTag: clickedButton?.tagName ?? null,
|
|
21963
|
-
buttonOnMedia,
|
|
21964
|
-
isMediaEditableEditable: isMediaEditable(editable)
|
|
21965
|
-
});
|
|
21966
23984
|
if (isMediaEditable(editable) && !buttonOnMedia) {
|
|
21967
23985
|
e.preventDefault();
|
|
21968
23986
|
e.stopPropagation();
|
|
@@ -21997,11 +24015,6 @@ function OhhwellsBridge() {
|
|
|
21997
24015
|
const hrefLookupTarget = buttonOnMedia ? clickedButton : editable;
|
|
21998
24016
|
const hrefCtx = getHrefKeyFromElement(hrefLookupTarget);
|
|
21999
24017
|
const navAnchor = hrefCtx ? getNavigationItemAnchor(hrefCtx.anchor) : null;
|
|
22000
|
-
console.log("[click-debug 2]", {
|
|
22001
|
-
hrefLookupTargetTag: hrefLookupTarget.tagName,
|
|
22002
|
-
hrefCtx: hrefCtx ? { key: hrefCtx.key } : null,
|
|
22003
|
-
navAnchorTag: navAnchor?.tagName ?? null
|
|
22004
|
-
});
|
|
22005
24018
|
if (navAnchor) {
|
|
22006
24019
|
e.preventDefault();
|
|
22007
24020
|
e.stopPropagation();
|
|
@@ -22184,6 +24197,9 @@ function OhhwellsBridge() {
|
|
|
22184
24197
|
setHoveredItemRect(null);
|
|
22185
24198
|
hoveredNavContainerRef.current = null;
|
|
22186
24199
|
setHoveredNavContainerRect(null);
|
|
24200
|
+
siblingHintElRef.current = null;
|
|
24201
|
+
setSiblingHintRect(null);
|
|
24202
|
+
setSiblingHintRects([]);
|
|
22187
24203
|
return;
|
|
22188
24204
|
}
|
|
22189
24205
|
{
|
|
@@ -22304,7 +24320,6 @@ function OhhwellsBridge() {
|
|
|
22304
24320
|
hoveredNavContainerRef.current = null;
|
|
22305
24321
|
setHoveredNavContainerRect(null);
|
|
22306
24322
|
hoveredItemElRef.current = editable;
|
|
22307
|
-
setHoveredItemRect(isSelectedForHoverRef.current(editable) ? null : editable.getBoundingClientRect());
|
|
22308
24323
|
}
|
|
22309
24324
|
}
|
|
22310
24325
|
}
|
|
@@ -22517,6 +24532,20 @@ function OhhwellsBridge() {
|
|
|
22517
24532
|
}
|
|
22518
24533
|
return;
|
|
22519
24534
|
}
|
|
24535
|
+
const navbarCtaHit = findNavbarCtaAtPoint(x, y);
|
|
24536
|
+
if (navbarCtaHit) {
|
|
24537
|
+
hoveredNavContainerRef.current = null;
|
|
24538
|
+
setHoveredNavContainerRect(null);
|
|
24539
|
+
if (selected !== navbarCtaHit && !selected?.contains(navbarCtaHit)) {
|
|
24540
|
+
clearHrefKeyHover(navbarCtaHit);
|
|
24541
|
+
hoveredItemElRef.current = navbarCtaHit;
|
|
24542
|
+
setHoveredItemRect(navbarCtaHit.getBoundingClientRect());
|
|
24543
|
+
} else if (hoveredItemElRef.current === navbarCtaHit) {
|
|
24544
|
+
hoveredItemElRef.current = null;
|
|
24545
|
+
setHoveredItemRect(null);
|
|
24546
|
+
}
|
|
24547
|
+
return;
|
|
24548
|
+
}
|
|
22520
24549
|
const navContainers = Array.from(
|
|
22521
24550
|
document.querySelectorAll("[data-ohw-nav-container]")
|
|
22522
24551
|
);
|
|
@@ -22608,7 +24637,7 @@ function OhhwellsBridge() {
|
|
|
22608
24637
|
};
|
|
22609
24638
|
const probeImageAt = (clientX, clientY, isDragOver = false, fromParentViewport = false) => {
|
|
22610
24639
|
syncSelectedMediaPointerRelease(true);
|
|
22611
|
-
if (linkPopoverOpenRef.current) {
|
|
24640
|
+
if (linkPopoverOpenRef.current || floatingPanelOpenRef.current && isPointOverFloatingPanel(clientX, clientY)) {
|
|
22612
24641
|
if (hoveredImageRef.current) {
|
|
22613
24642
|
hoveredImageRef.current = null;
|
|
22614
24643
|
hoveredImageHasTextOverlapRef.current = false;
|
|
@@ -22619,6 +24648,24 @@ function OhhwellsBridge() {
|
|
|
22619
24648
|
return;
|
|
22620
24649
|
}
|
|
22621
24650
|
const { x, y } = toProbeCoords(clientX, clientY, fromParentViewport);
|
|
24651
|
+
if (!isDragOver) {
|
|
24652
|
+
const buttonHit = findButtonAtPoint(x, y);
|
|
24653
|
+
if (buttonHit) {
|
|
24654
|
+
dismissImageHover();
|
|
24655
|
+
if (findNavbarCtaAtPoint(x, y)) {
|
|
24656
|
+
probeNavigationHoverAt(x, y);
|
|
24657
|
+
return;
|
|
24658
|
+
}
|
|
24659
|
+
document.querySelectorAll("[data-ohw-hovered]").forEach((el) => el.removeAttribute("data-ohw-hovered"));
|
|
24660
|
+
const selected = selectedElRef.current;
|
|
24661
|
+
if (selected !== buttonHit && !selected?.contains(buttonHit)) {
|
|
24662
|
+
clearHrefKeyHover(buttonHit);
|
|
24663
|
+
hoveredItemElRef.current = buttonHit;
|
|
24664
|
+
setHoveredItemRect(buttonHit.getBoundingClientRect());
|
|
24665
|
+
}
|
|
24666
|
+
return;
|
|
24667
|
+
}
|
|
24668
|
+
}
|
|
22622
24669
|
if (isPointOverNavigation(x, y)) {
|
|
22623
24670
|
dismissImageHover();
|
|
22624
24671
|
probeNavigationHoverAt(x, y);
|
|
@@ -22982,7 +25029,11 @@ function OhhwellsBridge() {
|
|
|
22982
25029
|
};
|
|
22983
25030
|
const handleMouseMove = (e) => {
|
|
22984
25031
|
const { clientX, clientY } = e;
|
|
22985
|
-
if (pointOwnedByFloatingPanel(clientX, clientY))
|
|
25032
|
+
if (pointOwnedByFloatingPanel(clientX, clientY)) {
|
|
25033
|
+
dismissImageHover();
|
|
25034
|
+
clearImageHover();
|
|
25035
|
+
return;
|
|
25036
|
+
}
|
|
22986
25037
|
if (isNavDrawerOpen() && isPointOutsideOpenDrawer(clientX, clientY)) {
|
|
22987
25038
|
document.querySelectorAll("[data-ohw-hovered]").forEach((el) => el.removeAttribute("data-ohw-hovered"));
|
|
22988
25039
|
formHoverElRef.current = null;
|
|
@@ -23011,7 +25062,12 @@ function OhhwellsBridge() {
|
|
|
23011
25062
|
setHoveredItemRect(null);
|
|
23012
25063
|
hoveredNavContainerRef.current = null;
|
|
23013
25064
|
setHoveredNavContainerRect(null);
|
|
25065
|
+
siblingHintElRef.current = null;
|
|
25066
|
+
setSiblingHintRect(null);
|
|
25067
|
+
setSiblingHintRects([]);
|
|
23014
25068
|
dismissImageHover();
|
|
25069
|
+
clearImageHover();
|
|
25070
|
+
setSectionGap(null);
|
|
23015
25071
|
return;
|
|
23016
25072
|
}
|
|
23017
25073
|
if (probeSocialsRowAt(clientX, clientY)) return;
|
|
@@ -23023,7 +25079,11 @@ function OhhwellsBridge() {
|
|
|
23023
25079
|
if (e.data?.type !== "ow:pointer-sync") return;
|
|
23024
25080
|
const { clientX, clientY } = e.data;
|
|
23025
25081
|
if (typeof clientX !== "number" || typeof clientY !== "number") return;
|
|
23026
|
-
if (pointOwnedByFloatingPanel(clientX, clientY))
|
|
25082
|
+
if (pointOwnedByFloatingPanel(clientX, clientY)) {
|
|
25083
|
+
dismissImageHover();
|
|
25084
|
+
clearImageHover();
|
|
25085
|
+
return;
|
|
25086
|
+
}
|
|
23027
25087
|
if (isNavDrawerOpen() && isPointOutsideOpenDrawer(clientX, clientY)) return;
|
|
23028
25088
|
if (probeSocialsRowAt(clientX, clientY)) return;
|
|
23029
25089
|
probeSectionGapAt(clientX, clientY);
|
|
@@ -23040,6 +25100,11 @@ function OhhwellsBridge() {
|
|
|
23040
25100
|
return;
|
|
23041
25101
|
}
|
|
23042
25102
|
if (onNavDragOver(e)) return;
|
|
25103
|
+
if (buttonCollectionDragRef.current) {
|
|
25104
|
+
e.preventDefault();
|
|
25105
|
+
if (e.dataTransfer) e.dataTransfer.dropEffect = "move";
|
|
25106
|
+
return;
|
|
25107
|
+
}
|
|
23043
25108
|
e.preventDefault();
|
|
23044
25109
|
const el = findImageAtPoint(e.clientX, e.clientY, false);
|
|
23045
25110
|
if (!el) {
|
|
@@ -23064,6 +25129,7 @@ function OhhwellsBridge() {
|
|
|
23064
25129
|
};
|
|
23065
25130
|
const handleDrop = (e) => {
|
|
23066
25131
|
e.preventDefault();
|
|
25132
|
+
if (buttonCollectionDragRef.current || navDragRef.current || footerDragRef.current) return;
|
|
23067
25133
|
const el = findImageAtPoint(e.clientX, e.clientY, false);
|
|
23068
25134
|
if (!el) return;
|
|
23069
25135
|
const file = e.dataTransfer?.files?.[0];
|
|
@@ -23363,6 +25429,7 @@ function OhhwellsBridge() {
|
|
|
23363
25429
|
}
|
|
23364
25430
|
if (typeof content[STYLE_STORE_KEY] === "string") {
|
|
23365
25431
|
stylesRef.current = content[STYLE_STORE_KEY];
|
|
25432
|
+
document.querySelectorAll('[data-ohw-editable="form"]').forEach((f) => markFormFields(f));
|
|
23366
25433
|
applyStylesToDom(parseStyleStore(content[STYLE_STORE_KEY]));
|
|
23367
25434
|
}
|
|
23368
25435
|
applyBrandChrome(content);
|
|
@@ -23375,12 +25442,12 @@ function OhhwellsBridge() {
|
|
|
23375
25442
|
continue;
|
|
23376
25443
|
}
|
|
23377
25444
|
if (key === AI_SECTIONS_KEY) continue;
|
|
25445
|
+
if (key === LOGO_PLACEHOLDER_KEY) continue;
|
|
25446
|
+
if (LOGO_IMAGE_KEYS.includes(key) && !String(val ?? "").trim()) continue;
|
|
23378
25447
|
if (key === BRAND_KIT_KEY) continue;
|
|
23379
25448
|
if (key === STYLE_STORE_KEY) continue;
|
|
23380
25449
|
if (BRAND_CHROME_KEYS.has(key)) continue;
|
|
23381
|
-
if (key === LOGO_PLACEHOLDER_KEY) continue;
|
|
23382
25450
|
if (key === CUSTOM_CODE_AFTER_HEAD_KEY || key === CUSTOM_CODE_BEFORE_HEAD_KEY) continue;
|
|
23383
|
-
if (LOGO_IMAGE_KEYS.includes(key) && !String(val ?? "").trim()) continue;
|
|
23384
25451
|
if (applyVideoSettingNode(key, val)) continue;
|
|
23385
25452
|
if (applyCarouselNode(key, val)) continue;
|
|
23386
25453
|
document.querySelectorAll(`[data-ohw-key="${key}"]`).forEach((el) => {
|
|
@@ -23419,6 +25486,7 @@ function OhhwellsBridge() {
|
|
|
23419
25486
|
editContentRef.current = { ...editContentRef.current, ...content };
|
|
23420
25487
|
reconcileNavbarItemsFromContent(editContentRef.current);
|
|
23421
25488
|
reconcileFooterOrderFromContent(editContentRef.current);
|
|
25489
|
+
syncButtonsFromContent(document, editContentRef.current);
|
|
23422
25490
|
syncNavigationDragCursorAttrs();
|
|
23423
25491
|
if (typeof content[STYLE_STORE_KEY] === "string") {
|
|
23424
25492
|
applyStylesToDom(parseStyleStore(content[STYLE_STORE_KEY]));
|
|
@@ -23825,6 +25893,12 @@ function OhhwellsBridge() {
|
|
|
23825
25893
|
closeLinkPopoverRef.current();
|
|
23826
25894
|
return;
|
|
23827
25895
|
}
|
|
25896
|
+
if (floatingPanelOpenRef.current) {
|
|
25897
|
+
setFloatingPanelRef.current(null);
|
|
25898
|
+
deselectRef.current();
|
|
25899
|
+
deactivateRef.current();
|
|
25900
|
+
return;
|
|
25901
|
+
}
|
|
23828
25902
|
deselectRef.current();
|
|
23829
25903
|
deactivateRef.current();
|
|
23830
25904
|
clearMediaSelectionRef.current();
|
|
@@ -24123,8 +26197,12 @@ function OhhwellsBridge() {
|
|
|
24123
26197
|
if (inserted) {
|
|
24124
26198
|
const tracker = getSectionsTracker();
|
|
24125
26199
|
postToParentRef.current({ type: "ow:change", nodes: [{ key: "__ohw_sections", text: tracker.textContent ?? "[]" }] });
|
|
24126
|
-
const
|
|
24127
|
-
|
|
26200
|
+
const reportHeight = () => {
|
|
26201
|
+
const h = document.body.scrollHeight;
|
|
26202
|
+
if (h > 50) postToParentRef.current({ type: "ow:height", height: h });
|
|
26203
|
+
};
|
|
26204
|
+
reportHeight();
|
|
26205
|
+
setTimeout(reportHeight, 500);
|
|
24128
26206
|
}
|
|
24129
26207
|
};
|
|
24130
26208
|
const handleSwitchSchedule = (e) => {
|
|
@@ -24328,11 +26406,8 @@ function OhhwellsBridge() {
|
|
|
24328
26406
|
};
|
|
24329
26407
|
const handleParentScroll = (e) => {
|
|
24330
26408
|
if (e.data?.type !== "ow:parent-scroll") return;
|
|
24331
|
-
const { iframeOffsetTop, headerH, canvasH } = e.data;
|
|
24332
|
-
parentScrollRef.current = { iframeOffsetTop, headerH, canvasH };
|
|
24333
|
-
if (floatingPanelOpenRef.current) {
|
|
24334
|
-
setParentScrollSnap({ iframeOffsetTop, headerH, canvasH });
|
|
24335
|
-
}
|
|
26409
|
+
const { iframeOffsetTop, headerH, canvasH, promptBarH = 0 } = e.data;
|
|
26410
|
+
parentScrollRef.current = { iframeOffsetTop, headerH, canvasH, promptBarH };
|
|
24336
26411
|
if (visibleViewportRef.current) {
|
|
24337
26412
|
applyVisibleViewport(visibleViewportRef.current, parentScrollRef.current);
|
|
24338
26413
|
}
|
|
@@ -24556,10 +26631,10 @@ function OhhwellsBridge() {
|
|
|
24556
26631
|
window.removeEventListener("message", handleDeleteSection);
|
|
24557
26632
|
window.removeEventListener("message", handleDuplicateSection);
|
|
24558
26633
|
window.removeEventListener("message", handleDeactivate);
|
|
24559
|
-
document.documentElement.removeAttribute("data-ohw-panel-dragging");
|
|
24560
26634
|
window.removeEventListener("message", handleToastAction);
|
|
24561
26635
|
window.removeEventListener("message", handleFormCount);
|
|
24562
26636
|
window.removeEventListener("message", handleUiEscape);
|
|
26637
|
+
document.documentElement.removeAttribute("data-ohw-panel-dragging");
|
|
24563
26638
|
autoSaveTimers.current.forEach(clearTimeout);
|
|
24564
26639
|
autoSaveTimers.current.clear();
|
|
24565
26640
|
if (imageUnhoverTimerRef.current) clearTimeout(imageUnhoverTimerRef.current);
|
|
@@ -24722,6 +26797,97 @@ function OhhwellsBridge() {
|
|
|
24722
26797
|
unlockFooterDragInteraction();
|
|
24723
26798
|
};
|
|
24724
26799
|
}, [isEditMode]);
|
|
26800
|
+
(0, import_react19.useEffect)(() => {
|
|
26801
|
+
if (!isEditMode) return;
|
|
26802
|
+
const THRESHOLD = 10;
|
|
26803
|
+
const onPointerDown = (e) => {
|
|
26804
|
+
if (e.button !== 0) return;
|
|
26805
|
+
if (buttonCollectionDragRef.current || navDragRef.current || footerDragRef.current) return;
|
|
26806
|
+
if (buttonPointerDragRef.current) return;
|
|
26807
|
+
const target = e.target;
|
|
26808
|
+
if (!target) return;
|
|
26809
|
+
if (target.closest(
|
|
26810
|
+
'[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]'
|
|
26811
|
+
)) {
|
|
26812
|
+
return;
|
|
26813
|
+
}
|
|
26814
|
+
const fromTarget = target.closest('[data-ohw-role="navbar-button"]');
|
|
26815
|
+
const anchor = (fromTarget && !fromTarget.closest("[data-ohw-bridge]") ? fromTarget : null) ?? findNavbarCtaAtPoint(e.clientX, e.clientY);
|
|
26816
|
+
if (!anchor || !collectionDragEnabled(anchor)) return;
|
|
26817
|
+
disableNativeHrefDrag(anchor);
|
|
26818
|
+
setMediaHover(null);
|
|
26819
|
+
buttonPointerDragRef.current = {
|
|
26820
|
+
el: anchor,
|
|
26821
|
+
startX: e.clientX,
|
|
26822
|
+
startY: e.clientY,
|
|
26823
|
+
pointerId: e.pointerId,
|
|
26824
|
+
started: false
|
|
26825
|
+
};
|
|
26826
|
+
};
|
|
26827
|
+
const onPointerMove = (e) => {
|
|
26828
|
+
const pending = buttonPointerDragRef.current;
|
|
26829
|
+
if (!pending) return;
|
|
26830
|
+
if (pending.started) {
|
|
26831
|
+
e.preventDefault();
|
|
26832
|
+
clearTextSelection();
|
|
26833
|
+
const dragged = buttonCollectionDragRef.current;
|
|
26834
|
+
if (!dragged) return;
|
|
26835
|
+
refreshButtonDragVisuals(dragged, e.clientX, e.clientY);
|
|
26836
|
+
return;
|
|
26837
|
+
}
|
|
26838
|
+
const dx = e.clientX - pending.startX;
|
|
26839
|
+
const dy = e.clientY - pending.startY;
|
|
26840
|
+
if (dx * dx + dy * dy < THRESHOLD * THRESHOLD) return;
|
|
26841
|
+
e.preventDefault();
|
|
26842
|
+
pending.started = true;
|
|
26843
|
+
armFooterPressDrag();
|
|
26844
|
+
clearTextSelection();
|
|
26845
|
+
try {
|
|
26846
|
+
document.body.setPointerCapture(pending.pointerId);
|
|
26847
|
+
} catch {
|
|
26848
|
+
}
|
|
26849
|
+
if (linkPopoverOpenRef.current) setLinkPopoverRef.current(null);
|
|
26850
|
+
if (activeElRef.current) deactivateRef.current();
|
|
26851
|
+
ensureNavbarButtonCollection(pending.el, editContentRef.current);
|
|
26852
|
+
buttonCollectionDragRef.current = pending.el;
|
|
26853
|
+
lockFooterDuringDrag();
|
|
26854
|
+
setIsItemDragging(true);
|
|
26855
|
+
refreshButtonDragVisuals(pending.el, e.clientX, e.clientY);
|
|
26856
|
+
};
|
|
26857
|
+
const endPointerDrag = (e) => {
|
|
26858
|
+
const pending = buttonPointerDragRef.current;
|
|
26859
|
+
buttonPointerDragRef.current = null;
|
|
26860
|
+
try {
|
|
26861
|
+
if (document.body.hasPointerCapture(e.pointerId)) {
|
|
26862
|
+
document.body.releasePointerCapture(e.pointerId);
|
|
26863
|
+
}
|
|
26864
|
+
} catch {
|
|
26865
|
+
}
|
|
26866
|
+
if (!pending) return;
|
|
26867
|
+
if (!pending.started) {
|
|
26868
|
+
unlockFooterDragInteraction();
|
|
26869
|
+
return;
|
|
26870
|
+
}
|
|
26871
|
+
suppressNextClickRef.current = true;
|
|
26872
|
+
suppressClickUntilRef.current = Date.now() + 500;
|
|
26873
|
+
persistButtonCollectionDrag(pending.el, e.clientX);
|
|
26874
|
+
};
|
|
26875
|
+
const blockSelectStart = (e) => {
|
|
26876
|
+
if (buttonCollectionDragRef.current || buttonPointerDragRef.current?.started) e.preventDefault();
|
|
26877
|
+
};
|
|
26878
|
+
document.addEventListener("pointerdown", onPointerDown, true);
|
|
26879
|
+
document.addEventListener("pointermove", onPointerMove, true);
|
|
26880
|
+
document.addEventListener("pointerup", endPointerDrag, true);
|
|
26881
|
+
document.addEventListener("pointercancel", endPointerDrag, true);
|
|
26882
|
+
document.addEventListener("selectstart", blockSelectStart, true);
|
|
26883
|
+
return () => {
|
|
26884
|
+
document.removeEventListener("pointerdown", onPointerDown, true);
|
|
26885
|
+
document.removeEventListener("pointermove", onPointerMove, true);
|
|
26886
|
+
document.removeEventListener("pointerup", endPointerDrag, true);
|
|
26887
|
+
document.removeEventListener("pointercancel", endPointerDrag, true);
|
|
26888
|
+
document.removeEventListener("selectstart", blockSelectStart, true);
|
|
26889
|
+
};
|
|
26890
|
+
}, [isEditMode, persistButtonCollectionDrag, refreshButtonDragVisuals]);
|
|
24725
26891
|
(0, import_react19.useEffect)(() => {
|
|
24726
26892
|
const handler = (e) => {
|
|
24727
26893
|
if (e.data?.type !== "ow:request-schedule-config") return;
|
|
@@ -24762,7 +26928,7 @@ function OhhwellsBridge() {
|
|
|
24762
26928
|
postToParent2({
|
|
24763
26929
|
type: "ow:ready",
|
|
24764
26930
|
version: "1",
|
|
24765
|
-
bridgeVersion: "0.1.
|
|
26931
|
+
bridgeVersion: "0.1.122",
|
|
24766
26932
|
path: pathname,
|
|
24767
26933
|
nodes: collectEditableNodes(editContentRef.current),
|
|
24768
26934
|
sections
|
|
@@ -24841,12 +27007,12 @@ function OhhwellsBridge() {
|
|
|
24841
27007
|
return;
|
|
24842
27008
|
}
|
|
24843
27009
|
if (type !== "ow:logo-size-set") return;
|
|
24844
|
-
const
|
|
24845
|
-
if (!Number.isFinite(
|
|
24846
|
-
const next = editorViewport === "mobile" ? { ...logoSizeDraft, mobilePx:
|
|
27010
|
+
const px2 = Number(e.data.px);
|
|
27011
|
+
if (!Number.isFinite(px2)) return;
|
|
27012
|
+
const next = editorViewport === "mobile" ? { ...logoSizeDraft, mobilePx: px2, mobileFollowing: false } : {
|
|
24847
27013
|
...logoSizeDraft,
|
|
24848
|
-
desktopPx:
|
|
24849
|
-
mobilePx: logoSizeDraft.mobileFollowing ?
|
|
27014
|
+
desktopPx: px2,
|
|
27015
|
+
mobilePx: logoSizeDraft.mobileFollowing ? px2 : logoSizeDraft.mobilePx
|
|
24850
27016
|
};
|
|
24851
27017
|
setLogoSizeDraft(next);
|
|
24852
27018
|
persistLogoSizeDraft(session.placement, next);
|
|
@@ -24944,6 +27110,36 @@ function OhhwellsBridge() {
|
|
|
24944
27110
|
const handleDuplicateSelected = (0, import_react19.useCallback)(() => {
|
|
24945
27111
|
const selected = selectedElRef.current;
|
|
24946
27112
|
if (!selected || !isNavigationItem2(selected)) return;
|
|
27113
|
+
if (isCtaButton(selected)) {
|
|
27114
|
+
const id = buttonId(selected);
|
|
27115
|
+
if (!id) return;
|
|
27116
|
+
const tokens = tokensForButton(selected, true);
|
|
27117
|
+
if (!readAssignments(editContentRef.current)[id]) {
|
|
27118
|
+
const assignment = assignmentFor(selected, editContentRef.current, tokens);
|
|
27119
|
+
const assignments = withAssignment(editContentRef.current, id, assignment);
|
|
27120
|
+
editContentRef.current = {
|
|
27121
|
+
...editContentRef.current,
|
|
27122
|
+
[BUTTON_ASSIGNMENTS_KEY]: JSON.stringify(assignments)
|
|
27123
|
+
};
|
|
27124
|
+
applyButtonStyle(selected, assignment, tokens);
|
|
27125
|
+
}
|
|
27126
|
+
const result = duplicateButton(selected, editContentRef.current);
|
|
27127
|
+
if (!result) return;
|
|
27128
|
+
editContentRef.current = result.content;
|
|
27129
|
+
const copyHref = result.copy.getAttribute("data-ohw-href-key");
|
|
27130
|
+
const copyHrefVal = copyHref ? result.content[copyHref] : void 0;
|
|
27131
|
+
if (copyHref && copyHrefVal !== void 0) applyLinkByKey(copyHref, copyHrefVal);
|
|
27132
|
+
postToParent2({ type: "ow:change", nodes: result.nodes });
|
|
27133
|
+
enforceLinkHrefs();
|
|
27134
|
+
requestAnimationFrame(() => {
|
|
27135
|
+
selectRef.current(result.copy);
|
|
27136
|
+
requestAnimationFrame(() => {
|
|
27137
|
+
const el = selectedElRef.current;
|
|
27138
|
+
if (el?.isConnected) setToolbarRect(el.getBoundingClientRect());
|
|
27139
|
+
});
|
|
27140
|
+
});
|
|
27141
|
+
return;
|
|
27142
|
+
}
|
|
24947
27143
|
const hrefKey = selected.getAttribute("data-ohw-href-key");
|
|
24948
27144
|
if (!hrefKey) return;
|
|
24949
27145
|
const social = getSocialItem(selected);
|
|
@@ -25073,7 +27269,7 @@ function OhhwellsBridge() {
|
|
|
25073
27269
|
selectRef.current(result.anchor);
|
|
25074
27270
|
});
|
|
25075
27271
|
}
|
|
25076
|
-
}, [postToParent2]);
|
|
27272
|
+
}, [postToParent2, tokensForButton]);
|
|
25077
27273
|
const runPendingDeleteUndo = (0, import_react19.useCallback)(() => {
|
|
25078
27274
|
const pending = pendingDeleteUndoRef.current;
|
|
25079
27275
|
if (!pending) return false;
|
|
@@ -25085,6 +27281,38 @@ function OhhwellsBridge() {
|
|
|
25085
27281
|
const handleDeleteSelected = (0, import_react19.useCallback)(() => {
|
|
25086
27282
|
const selected = selectedElRef.current;
|
|
25087
27283
|
if (!selected) return false;
|
|
27284
|
+
if (isCtaButton(selected)) {
|
|
27285
|
+
if (!canDeleteButton(selected)) return false;
|
|
27286
|
+
const previousContent = editContentRef.current;
|
|
27287
|
+
const result = deleteButton(selected, previousContent);
|
|
27288
|
+
if (!result) return false;
|
|
27289
|
+
editContentRef.current = result.content;
|
|
27290
|
+
postToParent2({ type: "ow:change", nodes: result.nodes });
|
|
27291
|
+
const actionId = typeof crypto !== "undefined" && "randomUUID" in crypto ? crypto.randomUUID() : `delete-${Date.now()}`;
|
|
27292
|
+
const restoreNodes = result.nodes.map((node) => ({
|
|
27293
|
+
key: node.key,
|
|
27294
|
+
text: previousContent[node.key] ?? ""
|
|
27295
|
+
}));
|
|
27296
|
+
pendingDeleteUndoRef.current = {
|
|
27297
|
+
actionId,
|
|
27298
|
+
restore: () => {
|
|
27299
|
+
result.undo();
|
|
27300
|
+
editContentRef.current = { ...editContentRef.current, ...Object.fromEntries(restoreNodes.map((node) => [node.key, node.text])) };
|
|
27301
|
+
postToParent2({ type: "ow:change", nodes: restoreNodes });
|
|
27302
|
+
syncButtonsFromContent(document, editContentRef.current);
|
|
27303
|
+
}
|
|
27304
|
+
};
|
|
27305
|
+
deselectRef.current();
|
|
27306
|
+
postToParent2({
|
|
27307
|
+
type: "ow:toast",
|
|
27308
|
+
title: "Button deleted",
|
|
27309
|
+
toastType: "success",
|
|
27310
|
+
actionLabel: "Undo",
|
|
27311
|
+
actionId,
|
|
27312
|
+
duration: 6e3
|
|
27313
|
+
});
|
|
27314
|
+
return true;
|
|
27315
|
+
}
|
|
25088
27316
|
return deleteSelectedNavFooterItem({
|
|
25089
27317
|
selected,
|
|
25090
27318
|
isTextEditing: Boolean(activeElRef.current),
|
|
@@ -25222,14 +27450,14 @@ function OhhwellsBridge() {
|
|
|
25222
27450
|
},
|
|
25223
27451
|
[postToParent2]
|
|
25224
27452
|
);
|
|
25225
|
-
return /* @__PURE__ */ (0,
|
|
25226
|
-
/* @__PURE__ */ (0,
|
|
25227
|
-
/* @__PURE__ */ (0,
|
|
25228
|
-
subdomain && !isEditMode && showBranding && /* @__PURE__ */ (0,
|
|
27453
|
+
return /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)(import_jsx_runtime36.Fragment, { children: [
|
|
27454
|
+
/* @__PURE__ */ (0, import_jsx_runtime36.jsx)("div", { id: "ohw-loader", suppressHydrationWarning: true, style: { ...OHW_LOADER_STYLE, display: "none" }, children: /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(OhwLoaderSpinner, {}) }),
|
|
27455
|
+
/* @__PURE__ */ (0, import_jsx_runtime36.jsx)("script", { suppressHydrationWarning: true, dangerouslySetInnerHTML: { __html: OHW_LOADER_PREHYDRATE_SCRIPT } }),
|
|
27456
|
+
subdomain && !isEditMode && showBranding && /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(MadeWithOhhWells, {}),
|
|
25229
27457
|
bridgeRoot ? (0, import_react_dom5.createPortal)(
|
|
25230
|
-
/* @__PURE__ */ (0,
|
|
25231
|
-
/* @__PURE__ */ (0,
|
|
25232
|
-
isEditMode && /* @__PURE__ */ (0,
|
|
27458
|
+
/* @__PURE__ */ (0, import_jsx_runtime36.jsxs)(import_jsx_runtime36.Fragment, { children: [
|
|
27459
|
+
/* @__PURE__ */ (0, import_jsx_runtime36.jsx)("div", { ref: attachVisibleViewport, "data-ohw-visible-viewport": "", "aria-hidden": true }),
|
|
27460
|
+
isEditMode && /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
|
|
25233
27461
|
AiSectionOverlay,
|
|
25234
27462
|
{
|
|
25235
27463
|
postToParent: postToParent2,
|
|
@@ -25237,7 +27465,7 @@ function OhhwellsBridge() {
|
|
|
25237
27465
|
onSelectionChange: handleAiSectionSelectionChange
|
|
25238
27466
|
}
|
|
25239
27467
|
),
|
|
25240
|
-
isEditMode && /* @__PURE__ */ (0,
|
|
27468
|
+
isEditMode && /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
|
|
25241
27469
|
AiMediaStripOverlay,
|
|
25242
27470
|
{
|
|
25243
27471
|
postToParent: postToParent2,
|
|
@@ -25246,7 +27474,7 @@ function OhhwellsBridge() {
|
|
|
25246
27474
|
clearInteractionChromeRef
|
|
25247
27475
|
}
|
|
25248
27476
|
),
|
|
25249
|
-
isEditMode && /* @__PURE__ */ (0,
|
|
27477
|
+
isEditMode && /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
|
|
25250
27478
|
AiPricingCardOverlay,
|
|
25251
27479
|
{
|
|
25252
27480
|
postToParent: postToParent2,
|
|
@@ -25254,12 +27482,12 @@ function OhhwellsBridge() {
|
|
|
25254
27482
|
applyTreeLocalRef
|
|
25255
27483
|
}
|
|
25256
27484
|
),
|
|
25257
|
-
isSectionDragging && sectionDropSlots.map((slot, i) => /* @__PURE__ */ (0,
|
|
27485
|
+
isSectionDragging && sectionDropSlots.map((slot, i) => /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
|
|
25258
27486
|
"div",
|
|
25259
27487
|
{
|
|
25260
27488
|
className: "pointer-events-none fixed z-2147483646",
|
|
25261
27489
|
style: { left: slot.left, top: slot.y, width: slot.width, height: 3, transform: "translateY(-50%)" },
|
|
25262
|
-
children: /* @__PURE__ */ (0,
|
|
27490
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
|
|
25263
27491
|
DropIndicator,
|
|
25264
27492
|
{
|
|
25265
27493
|
direction: "horizontal",
|
|
@@ -25270,7 +27498,7 @@ function OhhwellsBridge() {
|
|
|
25270
27498
|
},
|
|
25271
27499
|
`section-drop-${slot.insertIndex}-${i}`
|
|
25272
27500
|
)),
|
|
25273
|
-
Object.entries(uploadingRects).map(([key, { rect, fadingOut }]) => /* @__PURE__ */ (0,
|
|
27501
|
+
Object.entries(uploadingRects).map(([key, { rect, fadingOut }]) => /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
|
|
25274
27502
|
MediaOverlay,
|
|
25275
27503
|
{
|
|
25276
27504
|
hover: { key, rect, elementType: "image", isDragOver: false, hasTextOverlap: false },
|
|
@@ -25281,7 +27509,7 @@ function OhhwellsBridge() {
|
|
|
25281
27509
|
},
|
|
25282
27510
|
`uploading-${key}`
|
|
25283
27511
|
)),
|
|
25284
|
-
mediaHover && !(mediaHover.key in uploadingRects) && mediaHover.key !== selectedMedia?.key && /* @__PURE__ */ (0,
|
|
27512
|
+
mediaHover && !(mediaHover.key in uploadingRects) && mediaHover.key !== selectedMedia?.key && /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
|
|
25285
27513
|
MediaOverlay,
|
|
25286
27514
|
{
|
|
25287
27515
|
hover: mediaHover,
|
|
@@ -25292,7 +27520,7 @@ function OhhwellsBridge() {
|
|
|
25292
27520
|
onVideoSettingsChange: handleVideoSettingsChange
|
|
25293
27521
|
}
|
|
25294
27522
|
),
|
|
25295
|
-
selectedMedia && !(selectedMedia.key in uploadingRects) && !linkPopover && /* @__PURE__ */ (0,
|
|
27523
|
+
selectedMedia && !(selectedMedia.key in uploadingRects) && !linkPopover && /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
|
|
25296
27524
|
MediaOverlay,
|
|
25297
27525
|
{
|
|
25298
27526
|
hover: selectedMedia,
|
|
@@ -25304,7 +27532,7 @@ function OhhwellsBridge() {
|
|
|
25304
27532
|
onVideoSettingsChange: handleVideoSettingsChange
|
|
25305
27533
|
}
|
|
25306
27534
|
),
|
|
25307
|
-
carouselHover && !linkPopover && !isItemDragging && /* @__PURE__ */ (0,
|
|
27535
|
+
carouselHover && !linkPopover && !isItemDragging && /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
|
|
25308
27536
|
CarouselOverlay,
|
|
25309
27537
|
{
|
|
25310
27538
|
hover: carouselHover,
|
|
@@ -25312,10 +27540,10 @@ function OhhwellsBridge() {
|
|
|
25312
27540
|
cueOnly: !!carouselHover.fullBleedSectionId && carouselHover.fullBleedSectionId !== selectedAiSectionId
|
|
25313
27541
|
}
|
|
25314
27542
|
),
|
|
25315
|
-
siblingHintRect && !linkPopover && !isItemDragging && siblingHintRects.length === 0 && /* @__PURE__ */ (0,
|
|
25316
|
-
siblingHintRects.length > 0 && !linkPopover && !isItemDragging && siblingHintRects.map((rect, i) => /* @__PURE__ */ (0,
|
|
25317
|
-
isItemDragging && draggedItemRect && selectedElRef.current !== footerDragRef.current?.draggedEl && selectedElRef.current !== navDragRef.current?.draggedEl && /* @__PURE__ */ (0,
|
|
25318
|
-
isItemDragging && footerDropSlots.map((slot, i) => /* @__PURE__ */ (0,
|
|
27543
|
+
siblingHintRect && !linkPopover && !isItemDragging && siblingHintRects.length === 0 && /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(ItemInteractionLayer, { rect: siblingHintRect, state: "sibling-hint" }),
|
|
27544
|
+
siblingHintRects.length > 0 && !linkPopover && !isItemDragging && siblingHintRects.map((rect, i) => /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(ItemInteractionLayer, { rect, state: "sibling-hint" }, `sibling-hint-${i}`)),
|
|
27545
|
+
isItemDragging && draggedItemRect && selectedElRef.current !== footerDragRef.current?.draggedEl && selectedElRef.current !== navDragRef.current?.draggedEl && selectedElRef.current !== buttonCollectionDragRef.current && /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(ItemInteractionLayer, { rect: draggedItemRect, state: "dragging" }),
|
|
27546
|
+
isItemDragging && footerDropSlots.map((slot, i) => /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
|
|
25319
27547
|
"div",
|
|
25320
27548
|
{
|
|
25321
27549
|
className: "pointer-events-none fixed z-2147483646",
|
|
@@ -25325,7 +27553,7 @@ function OhhwellsBridge() {
|
|
|
25325
27553
|
width: slot.width,
|
|
25326
27554
|
height: slot.height
|
|
25327
27555
|
},
|
|
25328
|
-
children: /* @__PURE__ */ (0,
|
|
27556
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
|
|
25329
27557
|
DropIndicator,
|
|
25330
27558
|
{
|
|
25331
27559
|
direction: slot.direction,
|
|
@@ -25336,7 +27564,7 @@ function OhhwellsBridge() {
|
|
|
25336
27564
|
},
|
|
25337
27565
|
`footer-drop-${slot.direction}-${slot.columnIndex}-${slot.insertIndex}-${i}`
|
|
25338
27566
|
)),
|
|
25339
|
-
isItemDragging && navDropSlots.map((slot, i) => /* @__PURE__ */ (0,
|
|
27567
|
+
isItemDragging && navDropSlots.map((slot, i) => /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
|
|
25340
27568
|
"div",
|
|
25341
27569
|
{
|
|
25342
27570
|
className: "pointer-events-none fixed z-2147483646",
|
|
@@ -25346,7 +27574,7 @@ function OhhwellsBridge() {
|
|
|
25346
27574
|
width: slot.width,
|
|
25347
27575
|
height: slot.height
|
|
25348
27576
|
},
|
|
25349
|
-
children: /* @__PURE__ */ (0,
|
|
27577
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
|
|
25350
27578
|
DropIndicator,
|
|
25351
27579
|
{
|
|
25352
27580
|
direction: slot.direction,
|
|
@@ -25357,10 +27585,31 @@ function OhhwellsBridge() {
|
|
|
25357
27585
|
},
|
|
25358
27586
|
`nav-drop-${slot.direction}-${slot.parentId ?? "root"}-${slot.insertIndex}-${i}`
|
|
25359
27587
|
)),
|
|
25360
|
-
|
|
25361
|
-
|
|
25362
|
-
|
|
25363
|
-
|
|
27588
|
+
isItemDragging && buttonDropSlots.map((slot, i) => /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
|
|
27589
|
+
"div",
|
|
27590
|
+
{
|
|
27591
|
+
className: "pointer-events-none fixed z-2147483646",
|
|
27592
|
+
style: {
|
|
27593
|
+
left: slot.left,
|
|
27594
|
+
top: slot.top,
|
|
27595
|
+
width: slot.width,
|
|
27596
|
+
height: slot.height
|
|
27597
|
+
},
|
|
27598
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
|
|
27599
|
+
DropIndicator,
|
|
27600
|
+
{
|
|
27601
|
+
direction: slot.direction,
|
|
27602
|
+
state: activeButtonDropIndex === i ? "dragActive" : "dragIdle",
|
|
27603
|
+
className: "!h-full !w-full"
|
|
27604
|
+
}
|
|
27605
|
+
)
|
|
27606
|
+
},
|
|
27607
|
+
`button-drop-${slot.direction}-${slot.insertIndex}-${i}`
|
|
27608
|
+
)),
|
|
27609
|
+
hoveredNavContainerRect && (toolbarVariant !== "select-frame" || isFooterFrameSelection) && !linkPopover && !isItemDragging && /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(ItemInteractionLayer, { rect: hoveredNavContainerRect, state: "hover" }),
|
|
27610
|
+
hoveredItemRect && !linkPopover && !hoveredNavContainerRect && !isItemDragging && hoveredItemElRef.current !== selectedElRef.current && /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(ItemInteractionLayer, { rect: hoveredItemRect, state: "hover" }),
|
|
27611
|
+
hoveredTextRect && !hoveredNavContainerRect && !hoveredItemRect && !isItemDragging && toolbarVariant !== "rich-text" && /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(ItemInteractionLayer, { rect: hoveredTextRect, state: "hover" }),
|
|
27612
|
+
formPickRect && !isItemDragging && /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
|
|
25364
27613
|
ItemInteractionLayer,
|
|
25365
27614
|
{
|
|
25366
27615
|
rect: formPickRect,
|
|
@@ -25368,13 +27617,13 @@ function OhhwellsBridge() {
|
|
|
25368
27617
|
itemDragSurface: false,
|
|
25369
27618
|
toolbarAlign: "left",
|
|
25370
27619
|
chromeGap: 24,
|
|
25371
|
-
toolbar: fieldPickRect ? void 0 : /* @__PURE__ */ (0,
|
|
27620
|
+
toolbar: fieldPickRect ? void 0 : /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)(
|
|
25372
27621
|
"div",
|
|
25373
27622
|
{
|
|
25374
27623
|
"data-ohw-form-toolbar": "",
|
|
25375
27624
|
className: "pointer-events-auto flex items-center gap-0.5 whitespace-nowrap rounded-lg border border-border bg-background p-1 shadow-md",
|
|
25376
27625
|
children: [
|
|
25377
|
-
/* @__PURE__ */ (0,
|
|
27626
|
+
/* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
|
|
25378
27627
|
"button",
|
|
25379
27628
|
{
|
|
25380
27629
|
type: "button",
|
|
@@ -25382,11 +27631,11 @@ function OhhwellsBridge() {
|
|
|
25382
27631
|
className: "flex h-7 w-7 items-center justify-center rounded-md text-foreground transition-colors hover:bg-muted/80",
|
|
25383
27632
|
onClick: () => setFieldTypePickerOpen((open) => !open),
|
|
25384
27633
|
"data-ohw-add-field": "",
|
|
25385
|
-
children: /* @__PURE__ */ (0,
|
|
27634
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(import_lucide_react20.Plus, { size: 15, "aria-hidden": true })
|
|
25386
27635
|
}
|
|
25387
27636
|
),
|
|
25388
|
-
/* @__PURE__ */ (0,
|
|
25389
|
-
/* @__PURE__ */ (0,
|
|
27637
|
+
/* @__PURE__ */ (0, import_jsx_runtime36.jsx)("div", { className: "mx-0.5 h-5 w-px bg-border" }),
|
|
27638
|
+
/* @__PURE__ */ (0, import_jsx_runtime36.jsxs)(
|
|
25390
27639
|
"button",
|
|
25391
27640
|
{
|
|
25392
27641
|
type: "button",
|
|
@@ -25402,11 +27651,11 @@ function OhhwellsBridge() {
|
|
|
25402
27651
|
});
|
|
25403
27652
|
},
|
|
25404
27653
|
children: [
|
|
25405
|
-
/* @__PURE__ */ (0,
|
|
27654
|
+
/* @__PURE__ */ (0, import_jsx_runtime36.jsx)(import_lucide_react20.Settings, { size: 14, "aria-hidden": true }),
|
|
25406
27655
|
"Form settings",
|
|
25407
27656
|
formPickCount ? (
|
|
25408
27657
|
// Counter pill, per the design — not a text suffix.
|
|
25409
|
-
/* @__PURE__ */ (0,
|
|
27658
|
+
/* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
|
|
25410
27659
|
"span",
|
|
25411
27660
|
{
|
|
25412
27661
|
"data-ohw-form-count": "",
|
|
@@ -25418,8 +27667,8 @@ function OhhwellsBridge() {
|
|
|
25418
27667
|
]
|
|
25419
27668
|
}
|
|
25420
27669
|
),
|
|
25421
|
-
/* @__PURE__ */ (0,
|
|
25422
|
-
/* @__PURE__ */ (0,
|
|
27670
|
+
/* @__PURE__ */ (0, import_jsx_runtime36.jsx)("div", { className: "mx-0.5 h-5 w-px bg-border" }),
|
|
27671
|
+
/* @__PURE__ */ (0, import_jsx_runtime36.jsx)("div", { className: "flex items-center rounded-md bg-muted/70 p-0.5", children: ["default", "success"].map((state) => /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
|
|
25423
27672
|
"button",
|
|
25424
27673
|
{
|
|
25425
27674
|
type: "button",
|
|
@@ -25450,7 +27699,7 @@ function OhhwellsBridge() {
|
|
|
25450
27699
|
)
|
|
25451
27700
|
}
|
|
25452
27701
|
),
|
|
25453
|
-
formHoverRect && !isItemDragging && /* @__PURE__ */ (0,
|
|
27702
|
+
formHoverRect && !isItemDragging && /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
|
|
25454
27703
|
ItemInteractionLayer,
|
|
25455
27704
|
{
|
|
25456
27705
|
rect: formHoverRect,
|
|
@@ -25458,7 +27707,7 @@ function OhhwellsBridge() {
|
|
|
25458
27707
|
chromeGap: formHoverElRef.current && getFieldWrapper(formHoverElRef.current) ? 8 : 24
|
|
25459
27708
|
}
|
|
25460
27709
|
),
|
|
25461
|
-
fieldPickRect && fieldPickState && !isItemDragging && toolbarVariant !== "rich-text" && /* @__PURE__ */ (0,
|
|
27710
|
+
fieldPickRect && fieldPickState && !isItemDragging && toolbarVariant !== "rich-text" && /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
|
|
25462
27711
|
ItemInteractionLayer,
|
|
25463
27712
|
{
|
|
25464
27713
|
rect: fieldPickRect,
|
|
@@ -25470,7 +27719,7 @@ function OhhwellsBridge() {
|
|
|
25470
27719
|
dragHandleLabel: "Reorder field",
|
|
25471
27720
|
onDragHandleDragStart: handleFieldDragStart,
|
|
25472
27721
|
onDragHandleDragEnd: handleFieldDragEnd,
|
|
25473
|
-
toolbar: /* @__PURE__ */ (0,
|
|
27722
|
+
toolbar: /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
|
|
25474
27723
|
FormFieldToolbar,
|
|
25475
27724
|
{
|
|
25476
27725
|
type: fieldPickState.type,
|
|
@@ -25483,12 +27732,12 @@ function OhhwellsBridge() {
|
|
|
25483
27732
|
)
|
|
25484
27733
|
}
|
|
25485
27734
|
),
|
|
25486
|
-
fieldDragging ? fieldDropSlots.map((slot, i) => /* @__PURE__ */ (0,
|
|
27735
|
+
fieldDragging ? fieldDropSlots.map((slot, i) => /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
|
|
25487
27736
|
"div",
|
|
25488
27737
|
{
|
|
25489
27738
|
className: "pointer-events-none fixed z-[2147483644]",
|
|
25490
27739
|
style: { top: slot.top, left: slot.left, width: slot.width },
|
|
25491
|
-
children: /* @__PURE__ */ (0,
|
|
27740
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
|
|
25492
27741
|
DropIndicator,
|
|
25493
27742
|
{
|
|
25494
27743
|
direction: "horizontal",
|
|
@@ -25501,7 +27750,7 @@ function OhhwellsBridge() {
|
|
|
25501
27750
|
)) : null,
|
|
25502
27751
|
fieldTypePickerOpen && formPickRect ? (() => {
|
|
25503
27752
|
const toolbar = document.querySelector("[data-ohw-form-toolbar]")?.getBoundingClientRect();
|
|
25504
|
-
return /* @__PURE__ */ (0,
|
|
27753
|
+
return /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
|
|
25505
27754
|
"div",
|
|
25506
27755
|
{
|
|
25507
27756
|
className: "pointer-events-none fixed z-[2147483645]",
|
|
@@ -25509,12 +27758,12 @@ function OhhwellsBridge() {
|
|
|
25509
27758
|
top: toolbar ? toolbar.bottom + 6 : formPickRect.top + 16,
|
|
25510
27759
|
left: toolbar ? toolbar.left : formPickRect.left + 24
|
|
25511
27760
|
},
|
|
25512
|
-
children: /* @__PURE__ */ (0,
|
|
27761
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(FieldTypePicker, { onPick: handleAddField })
|
|
25513
27762
|
}
|
|
25514
27763
|
);
|
|
25515
27764
|
})() : null,
|
|
25516
|
-
toolbarVariant === "select-frame" && toolbarRect && !linkPopover && !isItemDragging && !isFooterFrameSelection && selectedElRef.current && isNavbarLinksContainer2(selectedElRef.current) && /* @__PURE__ */ (0,
|
|
25517
|
-
toolbarVariant === "select-frame" && toolbarRect && !linkPopover && !isItemDragging && !isFooterFrameSelection && selectedElRef.current && isFooterLinksContainer(selectedElRef.current) && /* @__PURE__ */ (0,
|
|
27765
|
+
toolbarVariant === "select-frame" && toolbarRect && !linkPopover && !isItemDragging && !isFooterFrameSelection && selectedElRef.current && isNavbarLinksContainer2(selectedElRef.current) && /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(NavbarContainerChrome, { rect: toolbarRect, onAdd: handleAddTopLevelNavItem }),
|
|
27766
|
+
toolbarVariant === "select-frame" && toolbarRect && !linkPopover && !isItemDragging && !isFooterFrameSelection && selectedElRef.current && isFooterLinksContainer(selectedElRef.current) && /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
|
|
25518
27767
|
FooterContainerChrome,
|
|
25519
27768
|
{
|
|
25520
27769
|
rect: toolbarRect,
|
|
@@ -25522,13 +27771,17 @@ function OhhwellsBridge() {
|
|
|
25522
27771
|
addDisabled: !canAddFooterColumn()
|
|
25523
27772
|
}
|
|
25524
27773
|
),
|
|
25525
|
-
toolbarRect && !linkPopover && (toolbarVariant === "link-action" || toolbarVariant === "select-frame" || toolbarVariant === "logo") && /* @__PURE__ */ (0,
|
|
27774
|
+
toolbarRect && !linkPopover && (toolbarVariant === "link-action" || toolbarVariant === "select-frame" || toolbarVariant === "logo") && /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
|
|
25526
27775
|
ItemInteractionLayer,
|
|
25527
27776
|
{
|
|
25528
|
-
rect: isItemDragging && draggedItemRect && (footerDragRef.current?.wasSelected || navDragRef.current?.wasSelected) ? draggedItemRect : toolbarRect,
|
|
27777
|
+
rect: isItemDragging && draggedItemRect && (footerDragRef.current?.wasSelected || navDragRef.current?.wasSelected || selectedElRef.current === buttonCollectionDragRef.current) ? draggedItemRect : toolbarRect,
|
|
25529
27778
|
toolbarBelowRect: selectedElRef.current && isNavigationItem2(selectedElRef.current) ? getOpenNavDropdownPanelRect(selectedElRef.current) : null,
|
|
25530
27779
|
toolbarBelowEl: selectedElRef.current && isNavigationItem2(selectedElRef.current) ? getOpenNavDropdownPanel(selectedElRef.current) : null,
|
|
25531
27780
|
elRef: glowElRef,
|
|
27781
|
+
hidden: isRectOutsideClip(
|
|
27782
|
+
isItemDragging && draggedItemRect && (footerDragRef.current?.wasSelected || navDragRef.current?.wasSelected || selectedElRef.current === buttonCollectionDragRef.current) ? draggedItemRect : toolbarRect,
|
|
27783
|
+
getIframeVisibleClip(parentScrollRef.current)
|
|
27784
|
+
),
|
|
25532
27785
|
state: isItemDragging ? "dragging" : selectedElRef.current && isNavigationItem2(selectedElRef.current) && getOpenNavDropdownPanel(selectedElRef.current) ? "active-bottom" : resolveItemInteractionState(toolbarRect, parentScrollRef.current),
|
|
25533
27786
|
showHandle: toolbarVariant === "link-action" && Boolean(reorderHrefKey) || toolbarVariant === "select-frame" && isFooterFrameSelection,
|
|
25534
27787
|
dragDisabled: reorderDragDisabled,
|
|
@@ -25538,18 +27791,25 @@ function OhhwellsBridge() {
|
|
|
25538
27791
|
onItemPointerDown: toolbarVariant === "logo" ? void 0 : handleItemChromePointerDown,
|
|
25539
27792
|
onItemClick: toolbarVariant === "logo" ? void 0 : handleItemChromeClick,
|
|
25540
27793
|
itemDragSurface: toolbarVariant !== "logo" && !isFooterFrameSelection && !selectedIsSocialsRow,
|
|
25541
|
-
toolbar: toolbarVariant === "link-action" && !isItemDragging || toolbarVariant === "select-frame" && (isFooterFrameSelection || selectedIsSocialsRow) && !isItemDragging ? /* @__PURE__ */ (0,
|
|
27794
|
+
toolbar: toolbarVariant === "link-action" && !isItemDragging || toolbarVariant === "select-frame" && (isFooterFrameSelection || selectedIsSocialsRow) && !isItemDragging ? /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
|
|
25542
27795
|
ItemActionToolbar,
|
|
25543
27796
|
{
|
|
25544
27797
|
onEditLink: openLinkPopoverForSelected,
|
|
25545
27798
|
onStyle: () => {
|
|
25546
27799
|
const row = selectedElRef.current;
|
|
25547
27800
|
if (!row) return;
|
|
25548
|
-
|
|
27801
|
+
suppressNextClickRef.current = true;
|
|
27802
|
+
suppressClickUntilRef.current = Date.now() + 500;
|
|
27803
|
+
if (isCtaButton(row)) {
|
|
27804
|
+
if (floatingPanelRef.current?.kind === "button-style") closeFloatingPanelOnly();
|
|
27805
|
+
else openButtonStylePanel(row);
|
|
27806
|
+
return;
|
|
27807
|
+
}
|
|
27808
|
+
if (floatingPanelRef.current?.kind === "socials-display") closeFloatingPanelOnly();
|
|
25549
27809
|
else openSocialsDisplayPanel(row);
|
|
25550
27810
|
},
|
|
25551
|
-
showStyle: selectedIsSocialsRow,
|
|
25552
|
-
styleActive: floatingPanel?.kind === "socials-display",
|
|
27811
|
+
showStyle: selectedIsSocialsRow || selectedIsCta,
|
|
27812
|
+
styleActive: floatingPanel?.kind === "socials-display" || floatingPanel?.kind === "button-style",
|
|
25553
27813
|
onAddItem: handleAddChildItem,
|
|
25554
27814
|
onSelectParent: handleSelectParent,
|
|
25555
27815
|
onDuplicate: handleDuplicateSelected,
|
|
@@ -25560,11 +27820,11 @@ function OhhwellsBridge() {
|
|
|
25560
27820
|
})(),
|
|
25561
27821
|
editLinkDisabled: false,
|
|
25562
27822
|
moreDisabled: false,
|
|
25563
|
-
deleteDisabled: selectedElRef.current !== null && (() => {
|
|
27823
|
+
deleteDisabled: selectedElRef.current !== null && isCtaButton(selectedElRef.current) && !canDeleteButton(selectedElRef.current) || selectedElRef.current !== null && (() => {
|
|
25564
27824
|
const social = getSocialItem(selectedElRef.current);
|
|
25565
27825
|
return social ? !canRemoveSocialItem(social) : false;
|
|
25566
27826
|
})(),
|
|
25567
|
-
duplicateDisabled: isFooterFrameSelection || selectedIsSocialsRow || selectedElRef.current !== null && (() => {
|
|
27827
|
+
duplicateDisabled: isFooterFrameSelection || selectedIsSocialsRow || selectedElRef.current !== null && isCtaButton(selectedElRef.current) && !canDuplicateButton(selectedElRef.current) || selectedElRef.current !== null && (() => {
|
|
25568
27828
|
const social = getSocialItem(selectedElRef.current);
|
|
25569
27829
|
const row = social ? findSocialsRow(social) : null;
|
|
25570
27830
|
return row ? !canAddSocialItem(row) : false;
|
|
@@ -25573,7 +27833,7 @@ function OhhwellsBridge() {
|
|
|
25573
27833
|
showAddItem: isFooterFrameSelection || selectedIsSocialsRow || !selectedIsCta && Boolean(
|
|
25574
27834
|
selectedElRef.current && isNavbarHrefKey(selectedElRef.current.getAttribute("data-ohw-href-key")) && !isNestedNavChild(selectedElRef.current)
|
|
25575
27835
|
),
|
|
25576
|
-
showMore:
|
|
27836
|
+
showMore: !selectedIsSocialsRow,
|
|
25577
27837
|
dropdownOpen: navDropdownPreviewOpen,
|
|
25578
27838
|
onDropdownOpenChange: handleNavDropdownOpenChange,
|
|
25579
27839
|
headingVisible: footerHeadingVisible,
|
|
@@ -25582,8 +27842,8 @@ function OhhwellsBridge() {
|
|
|
25582
27842
|
) : void 0
|
|
25583
27843
|
}
|
|
25584
27844
|
),
|
|
25585
|
-
toolbarRect && toolbarVariant === "rich-text" && !linkPopover && !isRectOutsideClip(toolbarRect, getIframeVisibleClip(parentScrollRef.current)) && /* @__PURE__ */ (0,
|
|
25586
|
-
/* @__PURE__ */ (0,
|
|
27845
|
+
toolbarRect && toolbarVariant === "rich-text" && !linkPopover && !isRectOutsideClip(toolbarRect, getIframeVisibleClip(parentScrollRef.current)) && /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)(import_jsx_runtime36.Fragment, { children: [
|
|
27846
|
+
/* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
|
|
25587
27847
|
EditGlowChrome,
|
|
25588
27848
|
{
|
|
25589
27849
|
rect: toolbarRect,
|
|
@@ -25593,7 +27853,7 @@ function OhhwellsBridge() {
|
|
|
25593
27853
|
hideHandle: isItemDragging
|
|
25594
27854
|
}
|
|
25595
27855
|
),
|
|
25596
|
-
/* @__PURE__ */ (0,
|
|
27856
|
+
/* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
|
|
25597
27857
|
FloatingToolbar,
|
|
25598
27858
|
{
|
|
25599
27859
|
rect: toolbarRect,
|
|
@@ -25606,7 +27866,7 @@ function OhhwellsBridge() {
|
|
|
25606
27866
|
}
|
|
25607
27867
|
)
|
|
25608
27868
|
] }),
|
|
25609
|
-
maxBadge && /* @__PURE__ */ (0,
|
|
27869
|
+
maxBadge && /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)(
|
|
25610
27870
|
"div",
|
|
25611
27871
|
{
|
|
25612
27872
|
"data-ohw-max-badge": "",
|
|
@@ -25632,7 +27892,7 @@ function OhhwellsBridge() {
|
|
|
25632
27892
|
]
|
|
25633
27893
|
}
|
|
25634
27894
|
),
|
|
25635
|
-
toggleState && !linkPopover && /* @__PURE__ */ (0,
|
|
27895
|
+
toggleState && !linkPopover && /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
|
|
25636
27896
|
StateToggle,
|
|
25637
27897
|
{
|
|
25638
27898
|
rect: toggleState.rect,
|
|
@@ -25641,15 +27901,15 @@ function OhhwellsBridge() {
|
|
|
25641
27901
|
onStateChange: handleStateChange
|
|
25642
27902
|
}
|
|
25643
27903
|
),
|
|
25644
|
-
sectionGap && !linkPopover && /* @__PURE__ */ (0,
|
|
27904
|
+
sectionGap && !linkPopover && /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)(
|
|
25645
27905
|
"div",
|
|
25646
27906
|
{
|
|
25647
27907
|
"data-ohw-section-insert-line": "",
|
|
25648
27908
|
className: "fixed left-0 w-full z-2147483646 flex items-center pointer-events-none",
|
|
25649
27909
|
style: { top: sectionGap.y, transform: "translateY(-50%)" },
|
|
25650
27910
|
children: [
|
|
25651
|
-
/* @__PURE__ */ (0,
|
|
25652
|
-
/* @__PURE__ */ (0,
|
|
27911
|
+
/* @__PURE__ */ (0, import_jsx_runtime36.jsx)("div", { className: "flex-1 bg-bridge-primary", style: { height: 3 } }),
|
|
27912
|
+
/* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
|
|
25653
27913
|
Badge,
|
|
25654
27914
|
{
|
|
25655
27915
|
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",
|
|
@@ -25666,11 +27926,11 @@ function OhhwellsBridge() {
|
|
|
25666
27926
|
children: "Add Section"
|
|
25667
27927
|
}
|
|
25668
27928
|
),
|
|
25669
|
-
/* @__PURE__ */ (0,
|
|
27929
|
+
/* @__PURE__ */ (0, import_jsx_runtime36.jsx)("div", { className: "flex-1 bg-bridge-primary", style: { height: 3 } })
|
|
25670
27930
|
]
|
|
25671
27931
|
}
|
|
25672
27932
|
),
|
|
25673
|
-
linkPopover && dialogPortalContainer ? /* @__PURE__ */ (0,
|
|
27933
|
+
linkPopover && dialogPortalContainer ? /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
|
|
25674
27934
|
LinkPopover,
|
|
25675
27935
|
{
|
|
25676
27936
|
panelRef: linkPopoverPanelRef,
|
|
@@ -25687,7 +27947,7 @@ function OhhwellsBridge() {
|
|
|
25687
27947
|
},
|
|
25688
27948
|
linkPopover.key
|
|
25689
27949
|
) : null,
|
|
25690
|
-
floatingPanel && floatingPanel.kind === "socials-display" ? /* @__PURE__ */ (0,
|
|
27950
|
+
floatingPanel && floatingPanel.kind === "socials-display" ? /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
|
|
25691
27951
|
FloatingPanel,
|
|
25692
27952
|
{
|
|
25693
27953
|
open: true,
|
|
@@ -25697,7 +27957,7 @@ function OhhwellsBridge() {
|
|
|
25697
27957
|
onPositionChange: setFloatingPanelPos,
|
|
25698
27958
|
parentScroll: parentScrollSnap ?? parentScrollRef.current,
|
|
25699
27959
|
onClose: closeFloatingPanelOnly,
|
|
25700
|
-
children: /* @__PURE__ */ (0,
|
|
27960
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
|
|
25701
27961
|
SocialsDisplayPanel,
|
|
25702
27962
|
{
|
|
25703
27963
|
display: socialsDisplayFor(floatingPanel.row, editContentRef.current),
|
|
@@ -25708,12 +27968,106 @@ function OhhwellsBridge() {
|
|
|
25708
27968
|
}
|
|
25709
27969
|
)
|
|
25710
27970
|
}
|
|
25711
|
-
) : null
|
|
27971
|
+
) : null,
|
|
27972
|
+
floatingPanel && floatingPanel.kind === "button-style" ? (() => {
|
|
27973
|
+
const button = document.querySelector(
|
|
27974
|
+
`[data-ohw-href-key="${CSS.escape(floatingPanel.buttonId)}"]`
|
|
27975
|
+
);
|
|
27976
|
+
if (!button) return null;
|
|
27977
|
+
captureButtonOrigin(button);
|
|
27978
|
+
const tokens = tokensFromButton(button);
|
|
27979
|
+
const current = assignmentFor(button, editContentRef.current, tokens);
|
|
27980
|
+
void buttonStyleTick;
|
|
27981
|
+
return /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
|
|
27982
|
+
FloatingPanel,
|
|
27983
|
+
{
|
|
27984
|
+
open: true,
|
|
27985
|
+
title: floatingPanel.title,
|
|
27986
|
+
context: floatingPanel.context,
|
|
27987
|
+
icon: /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(import_lucide_react20.Brush, { className: "size-4 shrink-0", "aria-hidden": true }),
|
|
27988
|
+
position: floatingPanelPos,
|
|
27989
|
+
onPositionChange: setFloatingPanelPos,
|
|
27990
|
+
parentScroll: parentScrollSnap ?? parentScrollRef.current,
|
|
27991
|
+
onClose: closeFloatingPanelOnly,
|
|
27992
|
+
bodyClassName: "gap-5",
|
|
27993
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
|
|
27994
|
+
ButtonStylePanel,
|
|
27995
|
+
{
|
|
27996
|
+
variants: tokens.variants,
|
|
27997
|
+
sizes: tokens.sizes,
|
|
27998
|
+
variant: current.variant,
|
|
27999
|
+
size: current.size,
|
|
28000
|
+
slotBackground: previewSlotBackground(button),
|
|
28001
|
+
previewLabel: (button.querySelector(
|
|
28002
|
+
'[data-ohw-editable="text"], [data-ohw-editable="plain"]'
|
|
28003
|
+
)?.textContent ?? button.textContent ?? "Book Now").trim() || "Book Now",
|
|
28004
|
+
onVariant: (variant) => applySelectedButtonStyle({ variant }),
|
|
28005
|
+
onSize: (size) => applySelectedButtonStyle({ size })
|
|
28006
|
+
},
|
|
28007
|
+
floatingPanel.key
|
|
28008
|
+
)
|
|
28009
|
+
},
|
|
28010
|
+
floatingPanel.key
|
|
28011
|
+
);
|
|
28012
|
+
})() : null
|
|
25712
28013
|
] }),
|
|
25713
28014
|
bridgeRoot
|
|
25714
28015
|
) : null
|
|
25715
28016
|
] });
|
|
25716
28017
|
}
|
|
28018
|
+
|
|
28019
|
+
// src/ui/EmptySection.tsx
|
|
28020
|
+
var import_link = __toESM(require("next/link"), 1);
|
|
28021
|
+
var import_jsx_runtime37 = require("react/jsx-runtime");
|
|
28022
|
+
function EmptySection({ title, homeHref = "/", eyebrowKey, titleKey, subtitleKey }) {
|
|
28023
|
+
return /* @__PURE__ */ (0, import_jsx_runtime37.jsxs)(import_jsx_runtime37.Fragment, { children: [
|
|
28024
|
+
/* @__PURE__ */ (0, import_jsx_runtime37.jsx)(
|
|
28025
|
+
"p",
|
|
28026
|
+
{
|
|
28027
|
+
style: {
|
|
28028
|
+
fontFamily: "var(--brand-font-body)",
|
|
28029
|
+
fontSize: "0.75rem",
|
|
28030
|
+
fontWeight: 500,
|
|
28031
|
+
letterSpacing: "0.15em",
|
|
28032
|
+
textTransform: "uppercase",
|
|
28033
|
+
color: "var(--brand-accent)",
|
|
28034
|
+
marginBottom: "1.5rem"
|
|
28035
|
+
},
|
|
28036
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(import_link.default, { href: homeHref, style: { color: "inherit" }, children: /* @__PURE__ */ (0, import_jsx_runtime37.jsx)("span", { ...eyebrowKey ? { "data-ohw-editable": "text", "data-ohw-key": eyebrowKey } : {}, children: "Home" }) })
|
|
28037
|
+
}
|
|
28038
|
+
),
|
|
28039
|
+
/* @__PURE__ */ (0, import_jsx_runtime37.jsx)(
|
|
28040
|
+
"h1",
|
|
28041
|
+
{
|
|
28042
|
+
style: {
|
|
28043
|
+
fontFamily: "var(--brand-font-heading)",
|
|
28044
|
+
fontSize: "clamp(2rem, 3.5vw, 2.75rem)",
|
|
28045
|
+
lineHeight: 1.1,
|
|
28046
|
+
letterSpacing: "-0.025em",
|
|
28047
|
+
color: "var(--brand-text)",
|
|
28048
|
+
marginBottom: "1rem"
|
|
28049
|
+
},
|
|
28050
|
+
...titleKey ? { "data-ohw-editable": "text", "data-ohw-key": titleKey, "data-ohw-max-length": 80 } : {},
|
|
28051
|
+
children: title
|
|
28052
|
+
}
|
|
28053
|
+
),
|
|
28054
|
+
/* @__PURE__ */ (0, import_jsx_runtime37.jsx)(
|
|
28055
|
+
"p",
|
|
28056
|
+
{
|
|
28057
|
+
style: {
|
|
28058
|
+
fontFamily: "var(--brand-font-body)",
|
|
28059
|
+
fontSize: "1rem",
|
|
28060
|
+
lineHeight: 1.7,
|
|
28061
|
+
fontWeight: 300,
|
|
28062
|
+
color: "var(--brand-text-muted)",
|
|
28063
|
+
maxWidth: "340px"
|
|
28064
|
+
},
|
|
28065
|
+
...subtitleKey ? { "data-ohw-editable": "text", "data-ohw-key": subtitleKey, "data-ohw-max-length": 160 } : {},
|
|
28066
|
+
children: "This page doesn't have any content yet."
|
|
28067
|
+
}
|
|
28068
|
+
)
|
|
28069
|
+
] });
|
|
28070
|
+
}
|
|
25717
28071
|
// Annotate the CommonJS export names for ESM import in node:
|
|
25718
28072
|
0 && (module.exports = {
|
|
25719
28073
|
AI_DEFAULT_BRAND,
|
|
@@ -25731,6 +28085,7 @@ function OhhwellsBridge() {
|
|
|
25731
28085
|
DropdownMenuItem,
|
|
25732
28086
|
DropdownMenuSeparator,
|
|
25733
28087
|
DropdownMenuTrigger,
|
|
28088
|
+
EmptySection,
|
|
25734
28089
|
ItemActionToolbar,
|
|
25735
28090
|
ItemInteractionLayer,
|
|
25736
28091
|
LinkEditorPanel,
|