@ohhwells/bridge 0.1.120 → 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 +2869 -466
- 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 +2867 -465
- 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,31 +650,84 @@ 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
|
|
|
697
|
+
// src/lib/custom-code.ts
|
|
698
|
+
var ALLOWED_HEAD_TAGS = /* @__PURE__ */ new Set(["style", "meta", "link", "script", "noscript", "base"]);
|
|
699
|
+
var CUSTOM_CODE_AFTER_HEAD_KEY = "__ohw_custom_code_after_head";
|
|
700
|
+
var CUSTOM_CODE_BEFORE_HEAD_KEY = "__ohw_custom_code_before_head";
|
|
701
|
+
function clearExisting(slot) {
|
|
702
|
+
document.querySelectorAll(`[data-ohw-custom-code="${slot}"]`).forEach((el) => el.remove());
|
|
703
|
+
}
|
|
704
|
+
function buildNodes(raw, slot) {
|
|
705
|
+
if (!raw || !raw.trim()) return [];
|
|
706
|
+
const parsed = new DOMParser().parseFromString(raw, "text/html");
|
|
707
|
+
const source = [...parsed.head.childNodes, ...parsed.body.childNodes];
|
|
708
|
+
const nodes = [];
|
|
709
|
+
for (const node of source) {
|
|
710
|
+
if (node.nodeType !== Node.ELEMENT_NODE) continue;
|
|
711
|
+
const el = node;
|
|
712
|
+
const tag = el.tagName.toLowerCase();
|
|
713
|
+
if (!ALLOWED_HEAD_TAGS.has(tag)) continue;
|
|
714
|
+
const built = document.createElement(tag);
|
|
715
|
+
for (const attr of Array.from(el.attributes)) built.setAttribute(attr.name, attr.value);
|
|
716
|
+
if (tag === "script" || tag === "style" || tag === "noscript") built.textContent = el.textContent;
|
|
717
|
+
built.dataset.ohwCustomCode = slot;
|
|
718
|
+
nodes.push(built);
|
|
719
|
+
}
|
|
720
|
+
return nodes;
|
|
721
|
+
}
|
|
722
|
+
function applyCustomCodeToHead(content) {
|
|
723
|
+
clearExisting("after");
|
|
724
|
+
clearExisting("before");
|
|
725
|
+
const afterNodes = buildNodes(content[CUSTOM_CODE_AFTER_HEAD_KEY], "after");
|
|
726
|
+
if (afterNodes.length > 0) document.head.prepend(...afterNodes);
|
|
727
|
+
const beforeNodes = buildNodes(content[CUSTOM_CODE_BEFORE_HEAD_KEY], "before");
|
|
728
|
+
if (beforeNodes.length > 0) document.head.append(...beforeNodes);
|
|
729
|
+
}
|
|
730
|
+
|
|
504
731
|
// src/lib/section-styles.ts
|
|
505
732
|
var STYLE_STORE_KEY = "__ohw_styles";
|
|
506
733
|
var STYLE_SHEET_ID = "ohw-section-styles";
|
|
@@ -564,9 +791,9 @@ function styleSheetCss() {
|
|
|
564
791
|
);
|
|
565
792
|
}
|
|
566
793
|
const pad = { tight: 40, balanced: 64, airy: 96 };
|
|
567
|
-
for (const [spacing,
|
|
794
|
+
for (const [spacing, px2] of Object.entries(pad)) {
|
|
568
795
|
rules.push(
|
|
569
|
-
`[data-ohw-style-spacing="${spacing}"] { padding-top: ${
|
|
796
|
+
`[data-ohw-style-spacing="${spacing}"] { padding-top: ${px2}px !important; padding-bottom: ${px2}px !important; }`
|
|
570
797
|
);
|
|
571
798
|
}
|
|
572
799
|
rules.push(
|
|
@@ -613,7 +840,6 @@ var NODE_PROPS = [
|
|
|
613
840
|
"color",
|
|
614
841
|
"font-family",
|
|
615
842
|
"font-size",
|
|
616
|
-
"background",
|
|
617
843
|
"text-align",
|
|
618
844
|
"justify-content",
|
|
619
845
|
"align-items"
|
|
@@ -663,9 +889,6 @@ function clearNodeProps(root) {
|
|
|
663
889
|
h.removeAttribute(NODE_WROTE_ATTR);
|
|
664
890
|
}
|
|
665
891
|
}
|
|
666
|
-
function buttonSurfaceOf(el) {
|
|
667
|
-
return el.closest("a, button") ?? el;
|
|
668
|
-
}
|
|
669
892
|
function alignSubjectOf(el) {
|
|
670
893
|
const button = el.closest('[data-ohw-role="button"]');
|
|
671
894
|
if (button?.parentElement) return button.parentElement;
|
|
@@ -783,18 +1006,6 @@ function applyStylesToDom(store) {
|
|
|
783
1006
|
);
|
|
784
1007
|
subject.setAttribute(NODE_WROTE_ATTR, "");
|
|
785
1008
|
}
|
|
786
|
-
if (override.buttonBackground !== void 0 || override.buttonText !== void 0) {
|
|
787
|
-
const surface = buttonSurfaceOf(el);
|
|
788
|
-
if (override.buttonBackground !== void 0) {
|
|
789
|
-
saveInline(surface, "background");
|
|
790
|
-
surface.style.setProperty("background", override.buttonBackground, "important");
|
|
791
|
-
}
|
|
792
|
-
if (override.buttonText !== void 0) {
|
|
793
|
-
saveInline(surface, "color");
|
|
794
|
-
surface.style.setProperty("color", override.buttonText, "important");
|
|
795
|
-
}
|
|
796
|
-
surface.setAttribute(NODE_WROTE_ATTR, "");
|
|
797
|
-
}
|
|
798
1009
|
}
|
|
799
1010
|
}
|
|
800
1011
|
for (const [sectionId, override] of Object.entries(store.sections)) {
|
|
@@ -1380,7 +1591,59 @@ var AI_MOBILE_CSS = [
|
|
|
1380
1591
|
"[data-ai-grid]{grid-template-columns:repeat(2, 1fr) !important}",
|
|
1381
1592
|
"}"
|
|
1382
1593
|
].join("");
|
|
1383
|
-
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
|
+
}
|
|
1384
1647
|
const bs = ctx.buttonStyle;
|
|
1385
1648
|
if (bs) {
|
|
1386
1649
|
return {
|
|
@@ -1490,6 +1753,22 @@ function pricingCardEmphasis(featured, ctx, hasBg) {
|
|
|
1490
1753
|
function textAttrs(ctx, path) {
|
|
1491
1754
|
return ctx.keyFor ? { "data-ohw-key": ctx.keyFor(path), "data-ohw-editable": "text" } : {};
|
|
1492
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");
|
|
1493
1772
|
var TRANSPARENT_PX = "data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7";
|
|
1494
1773
|
function MediaBox({
|
|
1495
1774
|
refValue,
|
|
@@ -1507,9 +1786,9 @@ function MediaBox({
|
|
|
1507
1786
|
const url = refValue ? ctx.resolveMedia(refValue) : null;
|
|
1508
1787
|
const isIcon = /^(lucide|simple):/.test(refValue);
|
|
1509
1788
|
const aspectRatio = aspect && /^\d+:\d+$/.test(aspect) ? aspect.replace(":", " / ") : void 0;
|
|
1510
|
-
const editAttrs = ctx.keyFor && editPath
|
|
1789
|
+
const editAttrs = ctx.keyFor && editPath ? {
|
|
1511
1790
|
"data-ohw-key": ctx.keyFor(editPath),
|
|
1512
|
-
...genericImageEdit ? { "data-ohw-editable": "image" } : {}
|
|
1791
|
+
...isIcon ? { "data-ohw-editable": "icon" } : genericImageEdit ? { "data-ohw-editable": "image" } : {}
|
|
1513
1792
|
} : {};
|
|
1514
1793
|
if (isIcon) {
|
|
1515
1794
|
const Icon = refValue.startsWith("lucide:") ? lucideByName(refValue.slice(7)) : null;
|
|
@@ -1517,6 +1796,7 @@ function MediaBox({
|
|
|
1517
1796
|
"span",
|
|
1518
1797
|
{
|
|
1519
1798
|
"data-ai-icon": refValue,
|
|
1799
|
+
...editAttrs,
|
|
1520
1800
|
style: {
|
|
1521
1801
|
display: "inline-flex",
|
|
1522
1802
|
width: 48,
|
|
@@ -1576,12 +1856,16 @@ function ButtonEl({
|
|
|
1576
1856
|
secondaryColor
|
|
1577
1857
|
}) {
|
|
1578
1858
|
const secondary = slots.variant === "secondary";
|
|
1859
|
+
const variant = secondary ? "secondary" : "primary";
|
|
1860
|
+
const tokenColorStyle = buttonColorStyle(ctx, variant);
|
|
1579
1861
|
const href = str(slots.href);
|
|
1580
1862
|
const linkAttrs = ctx.keyFor && path ? { "data-ohw-href-key": ctx.keyFor(`${path}.href`), "data-ohw-role": "button" } : {};
|
|
1581
1863
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1582
1864
|
"a",
|
|
1583
1865
|
{
|
|
1584
1866
|
href: href || void 0,
|
|
1867
|
+
className: `btn btn--${variant}`,
|
|
1868
|
+
"data-ohw-btn-variant": variant,
|
|
1585
1869
|
...linkAttrs,
|
|
1586
1870
|
style: {
|
|
1587
1871
|
display: fullWidth ? "flex" : "inline-flex",
|
|
@@ -1591,13 +1875,13 @@ function ButtonEl({
|
|
|
1591
1875
|
textDecoration: "none",
|
|
1592
1876
|
cursor: "pointer",
|
|
1593
1877
|
whiteSpace: "nowrap",
|
|
1594
|
-
...buttonShellStyle(ctx, fullWidth),
|
|
1595
|
-
...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 } : (
|
|
1596
1880
|
// Off-band, prefer the template button's measured fill/label pair — a template may
|
|
1597
1881
|
// fill its CTAs with any token (hvac: accent bg, primary text). On an accent band
|
|
1598
1882
|
// the flipped palette keeps contrast, so the brand-driven colours stay.
|
|
1599
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) }
|
|
1600
|
-
)
|
|
1884
|
+
))
|
|
1601
1885
|
},
|
|
1602
1886
|
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { ...path ? textAttrs(ctx, `${path}.label`) : {}, children: str(slots.label) })
|
|
1603
1887
|
}
|
|
@@ -2571,7 +2855,7 @@ function CollectionBlock({ node, ctx, path }) {
|
|
|
2571
2855
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
2572
2856
|
"div",
|
|
2573
2857
|
{
|
|
2574
|
-
"data-ai-grid":
|
|
2858
|
+
"data-ai-grid": String(itemsPerRow),
|
|
2575
2859
|
"data-ohw-pricing-collection": isPricing ? "" : void 0,
|
|
2576
2860
|
style: {
|
|
2577
2861
|
display: "grid",
|
|
@@ -2819,18 +3103,21 @@ function renderNode(node, ctx, path) {
|
|
|
2819
3103
|
"button",
|
|
2820
3104
|
{
|
|
2821
3105
|
type: "submit",
|
|
3106
|
+
className: "btn btn--primary",
|
|
3107
|
+
"data-ohw-btn-variant": "primary",
|
|
3108
|
+
"data-ohw-role": "button",
|
|
2822
3109
|
style: {
|
|
2823
3110
|
alignSelf: submitAlign,
|
|
2824
3111
|
border: "none",
|
|
2825
3112
|
cursor: "pointer",
|
|
2826
3113
|
// Shape/padding/typography follow the host template's own buttons.
|
|
2827
|
-
...buttonShellStyle(ctx),
|
|
3114
|
+
...buttonShellStyle(ctx, "primary"),
|
|
2828
3115
|
// Brand-styled: the template button's measured fill/label pair off-band, else
|
|
2829
3116
|
// primary fill with a brand-derived label so it reads on custom palettes.
|
|
2830
|
-
|
|
3117
|
+
...buttonColorStyle(ctx, "primary") ?? (!ctx.buttonLabel && ctx.buttonStyle?.background ? { background: ctx.buttonStyle.background, color: ctx.buttonStyle.color } : {
|
|
2831
3118
|
background: ctx.brand.palette.primary,
|
|
2832
3119
|
color: ctx.buttonLabel ?? primaryButtonLabel(ctx.brand)
|
|
2833
|
-
}
|
|
3120
|
+
})
|
|
2834
3121
|
},
|
|
2835
3122
|
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { ...textAttrs(ctx, `${path}.c${i}.label`), children: str(cs.label) })
|
|
2836
3123
|
},
|
|
@@ -2927,6 +3214,7 @@ function AiTreeRenderer({
|
|
|
2927
3214
|
{
|
|
2928
3215
|
"data-ai-section": tree.tag ?? "",
|
|
2929
3216
|
...bgAttrs,
|
|
3217
|
+
"data-ai-responsive": "",
|
|
2930
3218
|
style: {
|
|
2931
3219
|
position: "relative",
|
|
2932
3220
|
padding: `${pad}px 0`,
|
|
@@ -2937,12 +3225,13 @@ function AiTreeRenderer({
|
|
|
2937
3225
|
color: settings.sectionBackground === "accent" ? blockBrand.palette.dark : void 0
|
|
2938
3226
|
},
|
|
2939
3227
|
children: [
|
|
2940
|
-
|
|
3228
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("style", { children: AI_RESPONSIVE_CSS }),
|
|
2941
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})` } }),
|
|
2942
3231
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
2943
3232
|
"div",
|
|
2944
3233
|
{
|
|
2945
|
-
"data-ai-
|
|
3234
|
+
"data-ai-section-inner": "",
|
|
2946
3235
|
style: {
|
|
2947
3236
|
position: "relative",
|
|
2948
3237
|
maxWidth: AI_TREE_TOKENS.sectionMaxWidth,
|
|
@@ -2953,7 +3242,7 @@ function AiTreeRenderer({
|
|
|
2953
3242
|
children: tree.rows.map((row, r2) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
2954
3243
|
"div",
|
|
2955
3244
|
{
|
|
2956
|
-
"data-ai-
|
|
3245
|
+
"data-ai-columns": "",
|
|
2957
3246
|
style: {
|
|
2958
3247
|
display: "grid",
|
|
2959
3248
|
gridTemplateColumns: "repeat(12, 1fr)",
|
|
@@ -3133,12 +3422,12 @@ function deriveTemplateButtonStyle() {
|
|
|
3133
3422
|
cs.borderBottomLeftRadius
|
|
3134
3423
|
].map((v) => v || "0px");
|
|
3135
3424
|
const radius = corners.every((v) => v === corners[0]) ? corners[0] : corners.join(" ");
|
|
3136
|
-
const
|
|
3137
|
-
const lineHeight =
|
|
3138
|
-
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);
|
|
3139
3428
|
const impliedY = Math.round(Math.max(0, (contentH - lineHeight) / 2));
|
|
3140
|
-
const padY = Math.max(
|
|
3141
|
-
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));
|
|
3142
3431
|
return {
|
|
3143
3432
|
radius: radius || "10px",
|
|
3144
3433
|
padding: `${padY}px ${padX}px`,
|
|
@@ -3357,9 +3646,10 @@ function applyAiSectionsToDom(state, options) {
|
|
|
3357
3646
|
if (existing && existing.serialized === serialized && existing.container.isConnected) {
|
|
3358
3647
|
continue;
|
|
3359
3648
|
}
|
|
3360
|
-
const isNewMount = !existing || !existing.container.isConnected;
|
|
3361
3649
|
let container = existing?.container;
|
|
3650
|
+
let isNewMount = false;
|
|
3362
3651
|
if (!container || !container.isConnected) {
|
|
3652
|
+
isNewMount = true;
|
|
3363
3653
|
existing?.root.unmount();
|
|
3364
3654
|
container?.remove();
|
|
3365
3655
|
container = document.createElement("div");
|
|
@@ -8055,6 +8345,14 @@ function ItemActionToolbar({
|
|
|
8055
8345
|
e.preventDefault();
|
|
8056
8346
|
e.stopPropagation();
|
|
8057
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();
|
|
8058
8356
|
}
|
|
8059
8357
|
},
|
|
8060
8358
|
children: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(import_lucide_react3.Brush, { className: "size-4 shrink-0", "aria-hidden": true })
|
|
@@ -8377,20 +8675,32 @@ function ItemInteractionLayer({
|
|
|
8377
8675
|
itemDragSurface = true,
|
|
8378
8676
|
chromeGap,
|
|
8379
8677
|
toolbarAlign = "center",
|
|
8678
|
+
hidden = false,
|
|
8380
8679
|
className
|
|
8381
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]);
|
|
8382
8687
|
if (state === "default") return null;
|
|
8383
8688
|
const gap = chromeGap ?? (state === "hover" ? HOVER_CHROME_GAP : SELECTION_CHROME_GAP);
|
|
8384
8689
|
const isActive = state === "active-top" || state === "active-bottom";
|
|
8385
8690
|
const isDragging = state === "dragging";
|
|
8386
8691
|
const showToolbar = isActive && toolbar;
|
|
8387
8692
|
const showDragHandle = (isActive || isDragging) && showHandle;
|
|
8388
|
-
const itemDragEnabled = itemDragSurface && isActive &&
|
|
8693
|
+
const itemDragEnabled = itemDragSurface && isActive && !isDragging && !dragDisabled && Boolean(showHandle || onItemPointerDown);
|
|
8389
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
|
+
};
|
|
8390
8700
|
return /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(
|
|
8391
8701
|
"div",
|
|
8392
8702
|
{
|
|
8393
|
-
ref:
|
|
8703
|
+
ref: setRootRef,
|
|
8394
8704
|
"data-ohw-item-interaction": "",
|
|
8395
8705
|
"data-ohw-item-interaction-state": state,
|
|
8396
8706
|
className: cn("pointer-events-none", className),
|
|
@@ -8400,7 +8710,8 @@ function ItemInteractionLayer({
|
|
|
8400
8710
|
left: rect.left - gap,
|
|
8401
8711
|
width: rect.width + gap * 2,
|
|
8402
8712
|
height: rect.height + gap * 2,
|
|
8403
|
-
zIndex: getChromeZIndex(state)
|
|
8713
|
+
zIndex: getChromeZIndex(state),
|
|
8714
|
+
display: hidden ? "none" : "block"
|
|
8404
8715
|
},
|
|
8405
8716
|
children: [
|
|
8406
8717
|
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
@@ -9232,6 +9543,7 @@ function MediaOverlay({
|
|
|
9232
9543
|
(prev) => prev && prev.fullWidth === width && prev.height === height ? prev : { fullWidth: width, height }
|
|
9233
9544
|
);
|
|
9234
9545
|
}, [isVideo]);
|
|
9546
|
+
const replaceLabel = isVideo ? "Replace video" : hover.elementType === "bg-image" ? "Replace background" : "Replace image";
|
|
9235
9547
|
const replaceMode = buttonSize ? replaceButtonMode({ width: rect.width, height: rect.height }, buttonSize) : "none";
|
|
9236
9548
|
const box = {
|
|
9237
9549
|
position: "fixed",
|
|
@@ -9330,11 +9642,10 @@ function MediaOverlay({
|
|
|
9330
9642
|
className: "flex items-center justify-center cursor-pointer",
|
|
9331
9643
|
style: {
|
|
9332
9644
|
...box,
|
|
9333
|
-
//
|
|
9334
|
-
//
|
|
9335
|
-
//
|
|
9336
|
-
|
|
9337
|
-
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",
|
|
9338
9649
|
// Selected: a firm component ring with no wash, so the image reads as chosen rather
|
|
9339
9650
|
// than hovered. Hover keeps the existing tinted preview.
|
|
9340
9651
|
boxShadow: selected ? "inset 0 0 0 2px var(--color-bridge-primary)" : "inset 0 0 0 1.5px var(--color-bridge-primary)",
|
|
@@ -9361,17 +9672,17 @@ function MediaOverlay({
|
|
|
9361
9672
|
},
|
|
9362
9673
|
children: [
|
|
9363
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 }),
|
|
9364
|
-
|
|
9675
|
+
replaceLabel
|
|
9365
9676
|
]
|
|
9366
9677
|
}
|
|
9367
9678
|
),
|
|
9368
|
-
replaceMode
|
|
9679
|
+
showChrome && replaceMode !== "none" && /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(
|
|
9369
9680
|
Button,
|
|
9370
9681
|
{
|
|
9371
9682
|
"data-ohw-media-overlay": "",
|
|
9372
9683
|
variant: "outline",
|
|
9373
9684
|
size: "sm",
|
|
9374
|
-
"aria-label":
|
|
9685
|
+
"aria-label": replaceLabel,
|
|
9375
9686
|
className: "gap-1.5 cursor-pointer hover:bg-background",
|
|
9376
9687
|
style: {
|
|
9377
9688
|
...OVERLAY_BUTTON_STYLE,
|
|
@@ -9394,7 +9705,7 @@ function MediaOverlay({
|
|
|
9394
9705
|
},
|
|
9395
9706
|
children: [
|
|
9396
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 }),
|
|
9397
|
-
replaceMode === "full" ?
|
|
9708
|
+
replaceMode === "full" ? replaceLabel : null
|
|
9398
9709
|
]
|
|
9399
9710
|
}
|
|
9400
9711
|
)
|
|
@@ -11221,6 +11532,13 @@ function findButtonAtPoint(x, y, media) {
|
|
|
11221
11532
|
if (hits.length === 0) return null;
|
|
11222
11533
|
return hits.reduce((best, el) => best.contains(el) ? el : best);
|
|
11223
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
|
+
}
|
|
11224
11542
|
|
|
11225
11543
|
// src/lib/session-search.ts
|
|
11226
11544
|
var STORAGE_KEY = "ohw-preserved-search";
|
|
@@ -11956,6 +12274,26 @@ var import_react12 = require("react");
|
|
|
11956
12274
|
var import_react_dom3 = require("react-dom");
|
|
11957
12275
|
var import_lucide_react15 = require("lucide-react");
|
|
11958
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
|
|
11959
12297
|
var import_jsx_runtime27 = require("react/jsx-runtime");
|
|
11960
12298
|
var DIM_OVERLAY = "rgba(0, 0, 0, 0.45)";
|
|
11961
12299
|
function rectsEqual(a, b) {
|
|
@@ -12093,20 +12431,22 @@ function SectionPickerOverlay({
|
|
|
12093
12431
|
[]
|
|
12094
12432
|
);
|
|
12095
12433
|
(0, import_react12.useEffect)(() => {
|
|
12096
|
-
const applyClip = (iframeOffsetTop, visibleCanvasTop, canvasH) => {
|
|
12097
|
-
const
|
|
12098
|
-
|
|
12099
|
-
|
|
12100
|
-
|
|
12101
|
-
|
|
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;
|
|
12102
12442
|
setChromeClip(
|
|
12103
|
-
(prev) => prev.top === top && prev.bottom === bottom ? prev :
|
|
12443
|
+
(prev) => prev.top === next.top && prev.bottom === next.bottom ? prev : next
|
|
12104
12444
|
);
|
|
12105
12445
|
};
|
|
12106
12446
|
const onParentScroll = (e) => {
|
|
12107
12447
|
if (e.data?.type !== "ow:parent-scroll") return;
|
|
12108
|
-
const { iframeOffsetTop, headerH, canvasH } = e.data;
|
|
12109
|
-
applyClip(iframeOffsetTop, headerH, canvasH);
|
|
12448
|
+
const { iframeOffsetTop, headerH, canvasH, promptBarH = 0 } = e.data;
|
|
12449
|
+
applyClip(iframeOffsetTop, headerH, canvasH, promptBarH);
|
|
12110
12450
|
iframeOffsetTopRef.current = iframeOffsetTop;
|
|
12111
12451
|
if (!pointerScreenRef.current && pointerRef.current) {
|
|
12112
12452
|
pointerScreenRef.current = {
|
|
@@ -15699,6 +16039,7 @@ function readLogoSizeState(content, placement) {
|
|
|
15699
16039
|
function getLogoElement(el) {
|
|
15700
16040
|
const marked = el.closest('[data-ohw-role="logo"], [data-ohw-logo]');
|
|
15701
16041
|
if (marked) return marked;
|
|
16042
|
+
if (el.closest('[data-ohw-editable="icon"]')) return null;
|
|
15702
16043
|
const root = el.closest("nav, [data-ohw-nav-root], footer");
|
|
15703
16044
|
if (!root) return null;
|
|
15704
16045
|
const anchor = el.closest("a");
|
|
@@ -15770,36 +16111,50 @@ var import_lucide_react16 = require("lucide-react");
|
|
|
15770
16111
|
var import_jsx_runtime29 = require("react/jsx-runtime");
|
|
15771
16112
|
var PANEL_WIDTH = 256;
|
|
15772
16113
|
var EDGE_MARGIN = 16;
|
|
16114
|
+
var HEADER_MIN = 56;
|
|
15773
16115
|
function getVisibleClip(parentScroll) {
|
|
15774
16116
|
const left = 0;
|
|
15775
16117
|
const right = window.innerWidth;
|
|
15776
|
-
|
|
16118
|
+
const band = getIframeChromeClip(parentScroll);
|
|
16119
|
+
if (!band) {
|
|
15777
16120
|
return { top: 0, bottom: window.innerHeight, left, right };
|
|
15778
16121
|
}
|
|
15779
|
-
|
|
15780
|
-
const top = Math.max(0, visibleCanvasTop - iframeOffsetTop);
|
|
15781
|
-
const bottom = Math.min(window.innerHeight, visibleCanvasTop + canvasH - iframeOffsetTop);
|
|
15782
|
-
return { top, bottom: Math.max(top, bottom), left, right };
|
|
16122
|
+
return { ...band, left, right };
|
|
15783
16123
|
}
|
|
15784
|
-
function defaultFloatingPanelPosition(parentScroll,
|
|
16124
|
+
function defaultFloatingPanelPosition(parentScroll, _panelHeight = 280) {
|
|
15785
16125
|
const clip = getVisibleClip(parentScroll);
|
|
15786
16126
|
return {
|
|
15787
16127
|
x: Math.max(EDGE_MARGIN, clip.right - PANEL_WIDTH - EDGE_MARGIN),
|
|
15788
|
-
y:
|
|
15789
|
-
Math.max(clip.top + EDGE_MARGIN, EDGE_MARGIN),
|
|
15790
|
-
Math.max(clip.top + EDGE_MARGIN, clip.bottom - panelHeight - EDGE_MARGIN)
|
|
15791
|
-
)
|
|
16128
|
+
y: clip.top + EDGE_MARGIN
|
|
15792
16129
|
};
|
|
15793
16130
|
}
|
|
15794
|
-
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) {
|
|
15795
16137
|
const clip = getVisibleClip(parentScroll);
|
|
15796
|
-
const
|
|
15797
|
-
const maxY = Math.max(
|
|
16138
|
+
const minY = clip.top + EDGE_MARGIN;
|
|
16139
|
+
const maxY = Math.max(minY, clip.bottom - EDGE_MARGIN - HEADER_MIN);
|
|
15798
16140
|
return {
|
|
15799
|
-
x:
|
|
15800
|
-
y: Math.min(Math.max(pos.y,
|
|
16141
|
+
x: clampX(pos.x, panelW),
|
|
16142
|
+
y: Math.min(Math.max(pos.y, minY), maxY)
|
|
15801
16143
|
};
|
|
15802
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
|
+
}
|
|
15803
16158
|
function FloatingPanel({
|
|
15804
16159
|
open,
|
|
15805
16160
|
title,
|
|
@@ -15816,19 +16171,54 @@ function FloatingPanel({
|
|
|
15816
16171
|
const panelRef = (0, import_react15.useRef)(null);
|
|
15817
16172
|
const [measured, setMeasured] = (0, import_react15.useState)({ w: PANEL_WIDTH, h: 280 });
|
|
15818
16173
|
const dragRef = (0, import_react15.useRef)(null);
|
|
15819
|
-
const
|
|
15820
|
-
|
|
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]);
|
|
15821
16213
|
(0, import_react15.useLayoutEffect)(() => {
|
|
15822
16214
|
if (!open || !panelRef.current) return;
|
|
15823
16215
|
const el = panelRef.current;
|
|
15824
|
-
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 };
|
|
15825
16220
|
setMeasured((prev) => prev.w === next.w && prev.h === next.h ? prev : next);
|
|
15826
16221
|
}, [open, children, title, context]);
|
|
15827
|
-
(0, import_react15.useEffect)(() => {
|
|
15828
|
-
if (!open || !position || !onPositionChange) return;
|
|
15829
|
-
const next = clampPosition(position, parentScroll, measured.w, measured.h);
|
|
15830
|
-
if (next.x !== position.x || next.y !== position.y) onPositionChange(next);
|
|
15831
|
-
}, [open, parentScroll, measured.w, measured.h, position, onPositionChange]);
|
|
15832
16222
|
const onHeaderPointerDown = (0, import_react15.useCallback)(
|
|
15833
16223
|
(e) => {
|
|
15834
16224
|
if (e.button !== 0) return;
|
|
@@ -15862,18 +16252,17 @@ function FloatingPanel({
|
|
|
15862
16252
|
return;
|
|
15863
16253
|
}
|
|
15864
16254
|
e.preventDefault();
|
|
15865
|
-
const next =
|
|
16255
|
+
const next = clampDragPosition(
|
|
15866
16256
|
{
|
|
15867
16257
|
x: drag.originX + (e.clientX - drag.startX),
|
|
15868
16258
|
y: drag.originY + (e.clientY - drag.startY)
|
|
15869
16259
|
},
|
|
15870
|
-
|
|
15871
|
-
measured.w
|
|
15872
|
-
measured.h
|
|
16260
|
+
liveScroll,
|
|
16261
|
+
measured.w
|
|
15873
16262
|
);
|
|
15874
16263
|
onPositionChange?.(next);
|
|
15875
16264
|
},
|
|
15876
|
-
[measured.
|
|
16265
|
+
[measured.w, onPositionChange, liveScroll]
|
|
15877
16266
|
);
|
|
15878
16267
|
const endDrag = (0, import_react15.useCallback)((e) => {
|
|
15879
16268
|
const drag = dragRef.current;
|
|
@@ -15903,7 +16292,7 @@ function FloatingPanel({
|
|
|
15903
16292
|
"fixed z-[2147483647] flex w-64 flex-col overflow-hidden rounded-xl border border-border bg-background font-sans shadow-lg outline-none",
|
|
15904
16293
|
className
|
|
15905
16294
|
),
|
|
15906
|
-
style: { left: clamped.x, top: clamped.y },
|
|
16295
|
+
style: { left: clamped.x, top: clamped.y, maxHeight },
|
|
15907
16296
|
onMouseDown: (e) => e.stopPropagation(),
|
|
15908
16297
|
onPointerDown: (e) => e.stopPropagation(),
|
|
15909
16298
|
onClick: (e) => e.stopPropagation(),
|
|
@@ -15912,7 +16301,7 @@ function FloatingPanel({
|
|
|
15912
16301
|
"div",
|
|
15913
16302
|
{
|
|
15914
16303
|
"data-ohw-floating-panel-header": "",
|
|
15915
|
-
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",
|
|
15916
16305
|
onPointerDown: onHeaderPointerDown,
|
|
15917
16306
|
onPointerMove: onHeaderPointerMove,
|
|
15918
16307
|
onPointerUp: endDrag,
|
|
@@ -15947,7 +16336,11 @@ function FloatingPanel({
|
|
|
15947
16336
|
"div",
|
|
15948
16337
|
{
|
|
15949
16338
|
"data-ohw-floating-panel-body": "",
|
|
15950
|
-
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" },
|
|
15951
16344
|
children
|
|
15952
16345
|
}
|
|
15953
16346
|
)
|
|
@@ -16025,119 +16418,1553 @@ function SocialsDisplayPanel({ display, onChange, className }) {
|
|
|
16025
16418
|
] });
|
|
16026
16419
|
}
|
|
16027
16420
|
|
|
16028
|
-
// src/
|
|
16029
|
-
|
|
16030
|
-
|
|
16031
|
-
|
|
16032
|
-
|
|
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;
|
|
16033
16456
|
}
|
|
16457
|
+
return "var(--brand-background, var(--ohw-brand-light, var(--color-light, #ffffff)))";
|
|
16034
16458
|
}
|
|
16035
|
-
function
|
|
16036
|
-
|
|
16037
|
-
|
|
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;
|
|
16038
16464
|
}
|
|
16039
|
-
function
|
|
16040
|
-
|
|
16465
|
+
function isButtonVariantId(value) {
|
|
16466
|
+
return BUTTON_VARIANT_IDS.includes(value);
|
|
16041
16467
|
}
|
|
16042
|
-
function
|
|
16043
|
-
|
|
16044
|
-
document.documentElement.setAttribute("data-ohw-item-dragging", "");
|
|
16045
|
-
clearTextSelection();
|
|
16468
|
+
function isButtonSizeId(value) {
|
|
16469
|
+
return BUTTON_SIZE_IDS.includes(value);
|
|
16046
16470
|
}
|
|
16047
|
-
function
|
|
16048
|
-
const
|
|
16049
|
-
|
|
16050
|
-
document.documentElement.removeAttribute("data-ohw-item-dragging");
|
|
16051
|
-
if (wasDragging) clearTextSelection();
|
|
16471
|
+
function px(value) {
|
|
16472
|
+
const rounded = Math.round(value * 100) / 100;
|
|
16473
|
+
return `${rounded}px`;
|
|
16052
16474
|
}
|
|
16053
|
-
|
|
16054
|
-
|
|
16055
|
-
|
|
16056
|
-
|
|
16057
|
-
|
|
16058
|
-
|
|
16059
|
-
return listActiveNavbarItems(draggedEl).filter((el) => {
|
|
16060
|
-
const key = el.getAttribute("data-ohw-href-key");
|
|
16061
|
-
return isNavbarHrefKey(key) && !isNestedNavChild(el);
|
|
16062
|
-
});
|
|
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;
|
|
16063
16481
|
}
|
|
16064
|
-
function
|
|
16065
|
-
|
|
16066
|
-
|
|
16067
|
-
|
|
16068
|
-
const trigger = group.querySelector(":scope > [data-ohw-href-key]") ?? Array.from(group.querySelectorAll("[data-ohw-href-key]")).find(
|
|
16069
|
-
(el) => !el.closest("[data-ohw-nav-children]")
|
|
16070
|
-
) ?? null;
|
|
16071
|
-
const key = trigger?.getAttribute("data-ohw-href-key");
|
|
16072
|
-
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";
|
|
16073
16486
|
}
|
|
16074
|
-
function
|
|
16075
|
-
|
|
16076
|
-
|
|
16077
|
-
|
|
16078
|
-
|
|
16079
|
-
|
|
16080
|
-
|
|
16081
|
-
|
|
16082
|
-
(
|
|
16083
|
-
|
|
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
|
+
};
|
|
16084
16498
|
}
|
|
16085
|
-
function
|
|
16086
|
-
const
|
|
16087
|
-
|
|
16088
|
-
|
|
16089
|
-
|
|
16090
|
-
|
|
16091
|
-
|
|
16092
|
-
|
|
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
|
+
}
|
|
16093
16554
|
}
|
|
16094
|
-
const
|
|
16095
|
-
|
|
16096
|
-
|
|
16097
|
-
|
|
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;
|
|
16098
16575
|
}
|
|
16099
|
-
function
|
|
16100
|
-
|
|
16101
|
-
|
|
16102
|
-
|
|
16103
|
-
|
|
16104
|
-
|
|
16105
|
-
|
|
16106
|
-
|
|
16107
|
-
insertIndex: 0,
|
|
16108
|
-
parentId: null,
|
|
16109
|
-
left: rect.left,
|
|
16110
|
-
top: rect.top + rect.height / 2 - barThickness / 2,
|
|
16111
|
-
width: Math.max(rect.width, 40),
|
|
16112
|
-
height: barThickness,
|
|
16113
|
-
direction: "horizontal"
|
|
16114
|
-
});
|
|
16115
|
-
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;
|
|
16116
16584
|
}
|
|
16117
|
-
const
|
|
16118
|
-
|
|
16119
|
-
|
|
16120
|
-
|
|
16121
|
-
|
|
16122
|
-
|
|
16123
|
-
|
|
16124
|
-
|
|
16125
|
-
|
|
16126
|
-
|
|
16127
|
-
|
|
16128
|
-
|
|
16129
|
-
|
|
16130
|
-
|
|
16131
|
-
|
|
16132
|
-
|
|
16133
|
-
|
|
16134
|
-
|
|
16135
|
-
|
|
16136
|
-
|
|
16137
|
-
|
|
16138
|
-
|
|
16139
|
-
|
|
16140
|
-
|
|
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();
|
|
16141
17968
|
top = (prev.bottom + next.top) / 2 - barThickness / 2;
|
|
16142
17969
|
left = Math.min(prev.left, next.left);
|
|
16143
17970
|
width = Math.max(prev.right, next.right) - left;
|
|
@@ -16454,7 +18281,7 @@ function useNavItemDrag({
|
|
|
16454
18281
|
document.querySelectorAll(
|
|
16455
18282
|
"nav [data-ohw-href-key], [data-ohw-nav-container] [data-ohw-href-key], [data-ohw-nav-drawer] [data-ohw-href-key]"
|
|
16456
18283
|
).forEach((el) => {
|
|
16457
|
-
if (isNavbarHrefKey(el.getAttribute("data-ohw-href-key"))) {
|
|
18284
|
+
if (isNavbarHrefKey(el.getAttribute("data-ohw-href-key")) || isCtaButton(el)) {
|
|
16458
18285
|
disableNativeHrefDrag(el);
|
|
16459
18286
|
}
|
|
16460
18287
|
});
|
|
@@ -16763,12 +18590,6 @@ var SECTION_DRAG_EXCLUDED_SELECTOR = [
|
|
|
16763
18590
|
"[data-ohw-media-overlay]",
|
|
16764
18591
|
"[data-ohw-media-skeleton]"
|
|
16765
18592
|
].join(", ");
|
|
16766
|
-
function visibleClip(ps) {
|
|
16767
|
-
if (!ps) return null;
|
|
16768
|
-
const top = Math.max(0, ps.headerH - ps.iframeOffsetTop);
|
|
16769
|
-
const bottom = Math.min(window.innerHeight, ps.headerH + ps.canvasH - ps.iframeOffsetTop);
|
|
16770
|
-
return { top, bottom: Math.max(top, bottom) };
|
|
16771
|
-
}
|
|
16772
18593
|
function useSectionDrag({
|
|
16773
18594
|
isEditMode,
|
|
16774
18595
|
editContentRef,
|
|
@@ -16805,7 +18626,7 @@ function useSectionDrag({
|
|
|
16805
18626
|
}, [postToParentRef, stopAutoScroll]);
|
|
16806
18627
|
const updateAutoScroll = (0, import_react17.useCallback)(
|
|
16807
18628
|
(clientY) => {
|
|
16808
|
-
const clip =
|
|
18629
|
+
const clip = getIframeChromeClip(parentScrollRef.current);
|
|
16809
18630
|
let delta = 0;
|
|
16810
18631
|
if (clip) {
|
|
16811
18632
|
const distTop = clientY - clip.top;
|
|
@@ -17011,8 +18832,8 @@ function useSectionDrag({
|
|
|
17011
18832
|
}
|
|
17012
18833
|
|
|
17013
18834
|
// src/ui/footer-container-chrome.tsx
|
|
17014
|
-
var
|
|
17015
|
-
var
|
|
18835
|
+
var import_lucide_react18 = require("lucide-react");
|
|
18836
|
+
var import_jsx_runtime32 = require("react/jsx-runtime");
|
|
17016
18837
|
function FooterContainerChrome({
|
|
17017
18838
|
rect,
|
|
17018
18839
|
onAdd,
|
|
@@ -17020,7 +18841,7 @@ function FooterContainerChrome({
|
|
|
17020
18841
|
}) {
|
|
17021
18842
|
const chromeGap = 6;
|
|
17022
18843
|
const buttonMargin = 7;
|
|
17023
|
-
return /* @__PURE__ */ (0,
|
|
18844
|
+
return /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(TooltipProvider, { delayDuration: 0, children: /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
|
|
17024
18845
|
"div",
|
|
17025
18846
|
{
|
|
17026
18847
|
"data-ohw-footer-container-chrome": "",
|
|
@@ -17032,8 +18853,8 @@ function FooterContainerChrome({
|
|
|
17032
18853
|
width: rect.width + chromeGap * 2,
|
|
17033
18854
|
height: rect.height + chromeGap * 2
|
|
17034
18855
|
},
|
|
17035
|
-
children: /* @__PURE__ */ (0,
|
|
17036
|
-
/* @__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)(
|
|
17037
18858
|
"button",
|
|
17038
18859
|
{
|
|
17039
18860
|
type: "button",
|
|
@@ -17052,10 +18873,10 @@ function FooterContainerChrome({
|
|
|
17052
18873
|
if (addDisabled) return;
|
|
17053
18874
|
onAdd();
|
|
17054
18875
|
},
|
|
17055
|
-
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 })
|
|
17056
18877
|
}
|
|
17057
18878
|
) }),
|
|
17058
|
-
/* @__PURE__ */ (0,
|
|
18879
|
+
/* @__PURE__ */ (0, import_jsx_runtime32.jsx)(TooltipContent, { side: "bottom", sideOffset: 9, children: addDisabled ? "Maximum columns reached" : "Add item" })
|
|
17059
18880
|
] })
|
|
17060
18881
|
}
|
|
17061
18882
|
) });
|
|
@@ -17217,7 +19038,14 @@ function collectEditableNodes(extraContent, root = document) {
|
|
|
17217
19038
|
// so collecting the DOM alone left them behind: the draft knew the row was showing icons and
|
|
17218
19039
|
// had gained an item, and the published page went back to the template's own (OHH-736).
|
|
17219
19040
|
SOCIALS_ORDER_KEY,
|
|
17220
|
-
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
|
|
17221
19049
|
]) {
|
|
17222
19050
|
const text = extraContent[key];
|
|
17223
19051
|
if (typeof text === "string" && text.length > 0) {
|
|
@@ -17537,14 +19365,14 @@ function deleteSelectedNavFooterItem(deps) {
|
|
|
17537
19365
|
}
|
|
17538
19366
|
|
|
17539
19367
|
// src/ui/navbar-container-chrome.tsx
|
|
17540
|
-
var
|
|
17541
|
-
var
|
|
19368
|
+
var import_lucide_react19 = require("lucide-react");
|
|
19369
|
+
var import_jsx_runtime33 = require("react/jsx-runtime");
|
|
17542
19370
|
function NavbarContainerChrome({
|
|
17543
19371
|
rect,
|
|
17544
19372
|
onAdd
|
|
17545
19373
|
}) {
|
|
17546
19374
|
const chromeGap = 6;
|
|
17547
|
-
return /* @__PURE__ */ (0,
|
|
19375
|
+
return /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
|
|
17548
19376
|
"div",
|
|
17549
19377
|
{
|
|
17550
19378
|
"data-ohw-navbar-container-chrome": "",
|
|
@@ -17556,7 +19384,7 @@ function NavbarContainerChrome({
|
|
|
17556
19384
|
width: rect.width + chromeGap * 2,
|
|
17557
19385
|
height: rect.height + chromeGap * 2
|
|
17558
19386
|
},
|
|
17559
|
-
children: /* @__PURE__ */ (0,
|
|
19387
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
|
|
17560
19388
|
"button",
|
|
17561
19389
|
{
|
|
17562
19390
|
type: "button",
|
|
@@ -17573,7 +19401,7 @@ function NavbarContainerChrome({
|
|
|
17573
19401
|
e.stopPropagation();
|
|
17574
19402
|
onAdd();
|
|
17575
19403
|
},
|
|
17576
|
-
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 })
|
|
17577
19405
|
}
|
|
17578
19406
|
)
|
|
17579
19407
|
}
|
|
@@ -17582,7 +19410,7 @@ function NavbarContainerChrome({
|
|
|
17582
19410
|
|
|
17583
19411
|
// src/ui/drop-indicator.tsx
|
|
17584
19412
|
var React11 = __toESM(require("react"), 1);
|
|
17585
|
-
var
|
|
19413
|
+
var import_jsx_runtime34 = require("react/jsx-runtime");
|
|
17586
19414
|
var dropIndicatorVariants = cva(
|
|
17587
19415
|
"ov-gap-line pointer-events-none shrink-0 transition-opacity duration-150",
|
|
17588
19416
|
{
|
|
@@ -17606,7 +19434,7 @@ var dropIndicatorVariants = cva(
|
|
|
17606
19434
|
);
|
|
17607
19435
|
var DropIndicator = React11.forwardRef(
|
|
17608
19436
|
({ className, direction, state, ...props }, ref) => {
|
|
17609
|
-
return /* @__PURE__ */ (0,
|
|
19437
|
+
return /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
|
|
17610
19438
|
"div",
|
|
17611
19439
|
{
|
|
17612
19440
|
ref,
|
|
@@ -17623,7 +19451,7 @@ var DropIndicator = React11.forwardRef(
|
|
|
17623
19451
|
DropIndicator.displayName = "DropIndicator";
|
|
17624
19452
|
|
|
17625
19453
|
// src/ui/badge.tsx
|
|
17626
|
-
var
|
|
19454
|
+
var import_jsx_runtime35 = require("react/jsx-runtime");
|
|
17627
19455
|
var badgeVariants = cva(
|
|
17628
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",
|
|
17629
19457
|
{
|
|
@@ -17641,12 +19469,12 @@ var badgeVariants = cva(
|
|
|
17641
19469
|
}
|
|
17642
19470
|
);
|
|
17643
19471
|
function Badge({ className, variant, ...props }) {
|
|
17644
|
-
return /* @__PURE__ */ (0,
|
|
19472
|
+
return /* @__PURE__ */ (0, import_jsx_runtime35.jsx)("div", { className: cn(badgeVariants({ variant }), className), ...props });
|
|
17645
19473
|
}
|
|
17646
19474
|
|
|
17647
19475
|
// src/OhhwellsBridge.tsx
|
|
17648
|
-
var
|
|
17649
|
-
var
|
|
19476
|
+
var import_lucide_react20 = require("lucide-react");
|
|
19477
|
+
var import_jsx_runtime36 = require("react/jsx-runtime");
|
|
17650
19478
|
var PRIMARY5 = "#0885FE";
|
|
17651
19479
|
var IMAGE_FADE_MS = 300;
|
|
17652
19480
|
var MEDIA_SETTLE_TIMEOUT_MS = 2500;
|
|
@@ -17768,7 +19596,7 @@ function duplicateSchedulingWidget(instanceId, scheduleId) {
|
|
|
17768
19596
|
schedulingRoots.set(container, root);
|
|
17769
19597
|
(0, import_react_dom4.flushSync)(() => {
|
|
17770
19598
|
root.render(
|
|
17771
|
-
/* @__PURE__ */ (0,
|
|
19599
|
+
/* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
|
|
17772
19600
|
SchedulingWidget,
|
|
17773
19601
|
{
|
|
17774
19602
|
notifyOnConnect: false,
|
|
@@ -17811,21 +19639,10 @@ function parseSchedulingInsertAfter(insertAfter) {
|
|
|
17811
19639
|
insertBefore: insertAfter.slice(idx + INSERT_BEFORE_MARKER.length)
|
|
17812
19640
|
};
|
|
17813
19641
|
}
|
|
17814
|
-
function
|
|
17815
|
-
|
|
17816
|
-
const
|
|
17817
|
-
|
|
17818
|
-
return { effectiveInsertAfter, insertBefore };
|
|
17819
|
-
}
|
|
17820
|
-
function getSchedulingMountPoint(insertAfter) {
|
|
17821
|
-
const { anchor } = parseSchedulingInsertAfter(insertAfter);
|
|
17822
|
-
let anchorEl = document.querySelector(`[data-ohw-section="${anchor}"]`);
|
|
17823
|
-
if (!anchorEl && anchor === "scheduling") {
|
|
17824
|
-
const widgets = Array.from(document.querySelectorAll('[data-ohw-section^="scheduling-"]'));
|
|
17825
|
-
anchorEl = widgets.at(-1) ?? null;
|
|
17826
|
-
}
|
|
17827
|
-
if (!anchorEl) return null;
|
|
17828
|
-
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 };
|
|
17829
19646
|
}
|
|
17830
19647
|
function schedulingMountDepth(insertAfter) {
|
|
17831
19648
|
if (!insertAfter.includes(INSERT_BEFORE_MARKER)) return 0;
|
|
@@ -17842,8 +19659,7 @@ function getPageSchedulingEntries(raw) {
|
|
|
17842
19659
|
}
|
|
17843
19660
|
}
|
|
17844
19661
|
function isSchedulingWidgetMissing(entry) {
|
|
17845
|
-
|
|
17846
|
-
return !document.querySelector(`[data-ohw-section="${schedulingSectionId(effectiveInsertAfter)}"]`);
|
|
19662
|
+
return !document.querySelector(`[data-ohw-section="${schedulingSectionId(entry.insertAfter)}"]`);
|
|
17847
19663
|
}
|
|
17848
19664
|
function hasMissingSchedulingWidgets(entries) {
|
|
17849
19665
|
return entries.some(isSchedulingWidgetMissing);
|
|
@@ -17881,17 +19697,18 @@ function initSectionsFromContent(content, removeExisting = false, currentPath =
|
|
|
17881
19697
|
} catch {
|
|
17882
19698
|
}
|
|
17883
19699
|
}
|
|
17884
|
-
function mountSchedulingWidget(
|
|
17885
|
-
const
|
|
17886
|
-
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);
|
|
17887
19703
|
if (document.querySelector(`[data-ohw-section="${sectionId}"]`)) return false;
|
|
17888
|
-
const
|
|
17889
|
-
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;
|
|
17890
19707
|
const container = document.createElement("div");
|
|
17891
19708
|
container.dataset.ohwSectionContainer = "scheduling";
|
|
17892
19709
|
container.dataset.ohwInstance = sectionId;
|
|
17893
|
-
if (
|
|
17894
|
-
const beforeAnchor = document.querySelector(`[data-ohw-section="${
|
|
19710
|
+
if (beforeId) {
|
|
19711
|
+
const beforeAnchor = document.querySelector(`[data-ohw-section="${beforeId}"]`);
|
|
17895
19712
|
const beforePoint = beforeAnchor?.closest('[data-ohw-section-container="scheduling"]') ?? beforeAnchor;
|
|
17896
19713
|
if (!beforePoint) return false;
|
|
17897
19714
|
beforePoint.insertAdjacentElement("beforebegin", container);
|
|
@@ -17902,20 +19719,26 @@ function mountSchedulingWidget(insertAfter, notifyOnConnect = false, scheduleId,
|
|
|
17902
19719
|
}
|
|
17903
19720
|
tail.insertAdjacentElement("afterend", container);
|
|
17904
19721
|
}
|
|
17905
|
-
|
|
17906
|
-
|
|
17907
|
-
|
|
17908
|
-
|
|
17909
|
-
|
|
17910
|
-
|
|
17911
|
-
|
|
17912
|
-
|
|
17913
|
-
|
|
17914
|
-
|
|
17915
|
-
|
|
17916
|
-
|
|
17917
|
-
|
|
17918
|
-
|
|
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
|
+
}
|
|
17919
19742
|
const tracker = getSectionsTracker();
|
|
17920
19743
|
let sections = [];
|
|
17921
19744
|
try {
|
|
@@ -17923,10 +19746,12 @@ function mountSchedulingWidget(insertAfter, notifyOnConnect = false, scheduleId,
|
|
|
17923
19746
|
} catch {
|
|
17924
19747
|
}
|
|
17925
19748
|
const inEditor = typeof window !== "undefined" && window.self !== window.top;
|
|
17926
|
-
if (inEditor && !sections.find((s) => s.type === "scheduling" && s.insertAfter ===
|
|
19749
|
+
if (inEditor && !sections.find((s) => s.type === "scheduling" && s.insertAfter === widgetId)) {
|
|
17927
19750
|
sections.push({
|
|
17928
19751
|
type: "scheduling",
|
|
17929
|
-
insertAfter:
|
|
19752
|
+
insertAfter: widgetId,
|
|
19753
|
+
anchorId,
|
|
19754
|
+
beforeId: beforeId ?? null,
|
|
17930
19755
|
pagePath: window.location.pathname,
|
|
17931
19756
|
...scheduleId ? { scheduleId } : {}
|
|
17932
19757
|
});
|
|
@@ -17940,7 +19765,8 @@ function mountSchedulingEntries(entries, notifyOnConnect = false) {
|
|
|
17940
19765
|
for (let i = pending.length - 1; i >= 0; i--) {
|
|
17941
19766
|
const entry = pending[i];
|
|
17942
19767
|
const shouldNotify = typeof notifyOnConnect === "function" ? notifyOnConnect(entry) : notifyOnConnect;
|
|
17943
|
-
|
|
19768
|
+
const { anchorId, beforeId } = resolveEntryAnchor(entry);
|
|
19769
|
+
if (mountSchedulingWidget(anchorId, shouldNotify, entry.scheduleId ?? null, beforeId, entry.insertAfter)) {
|
|
17944
19770
|
pending.splice(i, 1);
|
|
17945
19771
|
}
|
|
17946
19772
|
}
|
|
@@ -18069,8 +19895,8 @@ function lockVideoBox(video) {
|
|
|
18069
19895
|
}
|
|
18070
19896
|
const fit = video.style.objectFit || getComputedStyle(video).objectFit;
|
|
18071
19897
|
const bg = getComputedStyle(video).backgroundColor;
|
|
18072
|
-
const
|
|
18073
|
-
if (fit === "contain" &&
|
|
19898
|
+
const isTransparent2 = bg === "rgba(0, 0, 0, 0)" || bg === "transparent" || !bg;
|
|
19899
|
+
if (fit === "contain" && isTransparent2) {
|
|
18074
19900
|
video.style.backgroundColor = "var(--color-dark, #000)";
|
|
18075
19901
|
}
|
|
18076
19902
|
}
|
|
@@ -18117,6 +19943,11 @@ function applyLinkByKey(key, val) {
|
|
|
18117
19943
|
hrefAnchors.forEach((el) => applyLinkHref(el, val));
|
|
18118
19944
|
}
|
|
18119
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
|
+
}
|
|
18120
19951
|
function isInsideFloatingPanel(target) {
|
|
18121
19952
|
return Boolean(target.closest("[data-ohw-floating-panel]"));
|
|
18122
19953
|
}
|
|
@@ -18124,11 +19955,6 @@ function isPointOverFloatingPanel(clientX, clientY) {
|
|
|
18124
19955
|
const el = document.elementFromPoint(clientX, clientY);
|
|
18125
19956
|
return Boolean(el instanceof Element && el.closest("[data-ohw-floating-panel]"));
|
|
18126
19957
|
}
|
|
18127
|
-
function isInsideLinkEditor(target) {
|
|
18128
|
-
return Boolean(
|
|
18129
|
-
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"]')
|
|
18130
|
-
);
|
|
18131
|
-
}
|
|
18132
19958
|
function getHrefKeyFromElement(el) {
|
|
18133
19959
|
if (!el) return null;
|
|
18134
19960
|
const anchor = el.closest("[data-ohw-href-key]");
|
|
@@ -18220,7 +20046,10 @@ function listNavigationItems() {
|
|
|
18220
20046
|
).filter((el) => isNavigationItem2(el));
|
|
18221
20047
|
}
|
|
18222
20048
|
function getNavigationItemReorderState(anchor) {
|
|
18223
|
-
if (isCtaButton(anchor))
|
|
20049
|
+
if (isCtaButton(anchor)) {
|
|
20050
|
+
if (!collectionDragEnabled(anchor)) return { key: null, disabled: true };
|
|
20051
|
+
return { key: buttonId(anchor), disabled: false };
|
|
20052
|
+
}
|
|
18224
20053
|
return getReorderHandleStateFromAnchor(anchor);
|
|
18225
20054
|
}
|
|
18226
20055
|
function getReorderHandleState(el) {
|
|
@@ -18319,6 +20148,12 @@ function isPointOverNavigation(x, y) {
|
|
|
18319
20148
|
const r2 = panel.getBoundingClientRect();
|
|
18320
20149
|
if (x >= r2.left && x <= r2.right && y >= r2.top && y <= r2.bottom) return true;
|
|
18321
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
|
+
}
|
|
18322
20157
|
return false;
|
|
18323
20158
|
}
|
|
18324
20159
|
function findHoveredNavOrFooterContainer(x, y) {
|
|
@@ -18398,7 +20233,7 @@ function getNavigationSelectionParent(el) {
|
|
|
18398
20233
|
if (!isFooterLinksContainer(el) && (el.hasAttribute("data-ohw-footer-col") || el.hasAttribute("data-ohw-footer-column") || isInferredFooterGroup2(el))) {
|
|
18399
20234
|
return getFooterLinksContainer();
|
|
18400
20235
|
}
|
|
18401
|
-
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)) {
|
|
18402
20237
|
return getNavigationRoot(el);
|
|
18403
20238
|
}
|
|
18404
20239
|
return null;
|
|
@@ -18620,7 +20455,6 @@ var ICONS = {
|
|
|
18620
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"/>',
|
|
18621
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"/>'
|
|
18622
20457
|
};
|
|
18623
|
-
var HEIGHT_SETTLE_DELAYS = [150, 400, 800];
|
|
18624
20458
|
var SELECTION_CHROME_GAP2 = 4;
|
|
18625
20459
|
var TOOLBAR_STROKE_GAP2 = 4;
|
|
18626
20460
|
var TOOLBAR_OFFSET_FROM_ELEMENT = SELECTION_CHROME_GAP2 + TOOLBAR_STROKE_GAP2;
|
|
@@ -18652,7 +20486,7 @@ function EditGlowChrome({
|
|
|
18652
20486
|
hideHandle = false
|
|
18653
20487
|
}) {
|
|
18654
20488
|
const GAP = SELECTION_CHROME_GAP2;
|
|
18655
|
-
return /* @__PURE__ */ (0,
|
|
20489
|
+
return /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)(
|
|
18656
20490
|
"div",
|
|
18657
20491
|
{
|
|
18658
20492
|
ref: elRef,
|
|
@@ -18667,7 +20501,7 @@ function EditGlowChrome({
|
|
|
18667
20501
|
zIndex: 2147483646
|
|
18668
20502
|
},
|
|
18669
20503
|
children: [
|
|
18670
|
-
/* @__PURE__ */ (0,
|
|
20504
|
+
/* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
|
|
18671
20505
|
"div",
|
|
18672
20506
|
{
|
|
18673
20507
|
style: {
|
|
@@ -18681,7 +20515,7 @@ function EditGlowChrome({
|
|
|
18681
20515
|
}
|
|
18682
20516
|
}
|
|
18683
20517
|
),
|
|
18684
|
-
reorderHrefKey && !hideHandle && /* @__PURE__ */ (0,
|
|
20518
|
+
reorderHrefKey && !hideHandle && /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
|
|
18685
20519
|
"div",
|
|
18686
20520
|
{
|
|
18687
20521
|
"data-ohw-drag-handle-container": "",
|
|
@@ -18693,7 +20527,7 @@ function EditGlowChrome({
|
|
|
18693
20527
|
transform: "translate(calc(-100% - 7px), -50%)",
|
|
18694
20528
|
pointerEvents: dragDisabled ? "none" : "auto"
|
|
18695
20529
|
},
|
|
18696
|
-
children: /* @__PURE__ */ (0,
|
|
20530
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
|
|
18697
20531
|
DragHandle,
|
|
18698
20532
|
{
|
|
18699
20533
|
"aria-label": `Reorder ${reorderHrefKey}`,
|
|
@@ -18707,22 +20541,12 @@ function EditGlowChrome({
|
|
|
18707
20541
|
}
|
|
18708
20542
|
);
|
|
18709
20543
|
}
|
|
18710
|
-
function getIframeVisibleClip(parentScroll) {
|
|
18711
|
-
if (!parentScroll) return null;
|
|
18712
|
-
const { iframeOffsetTop, headerH: visibleCanvasTop, canvasH } = parentScroll;
|
|
18713
|
-
const clipTop = Math.max(0, visibleCanvasTop - iframeOffsetTop);
|
|
18714
|
-
const clipBottom = Math.min(
|
|
18715
|
-
window.innerHeight,
|
|
18716
|
-
visibleCanvasTop + canvasH - iframeOffsetTop
|
|
18717
|
-
);
|
|
18718
|
-
return { top: clipTop, bottom: Math.max(clipTop, clipBottom) };
|
|
18719
|
-
}
|
|
18720
20544
|
function isRectOutsideClip(rect, clip) {
|
|
18721
20545
|
if (!clip) return false;
|
|
18722
20546
|
return rect.bottom < clip.top || rect.top > clip.bottom;
|
|
18723
20547
|
}
|
|
18724
20548
|
function applyVisibleViewport(el, parentScroll) {
|
|
18725
|
-
const clip =
|
|
20549
|
+
const clip = getIframeChromeClip(parentScroll);
|
|
18726
20550
|
const top = clip?.top ?? 0;
|
|
18727
20551
|
const height = clip ? clip.bottom - clip.top : window.innerHeight;
|
|
18728
20552
|
el.style.top = `${top}px`;
|
|
@@ -18762,7 +20586,7 @@ function clampToolbarLeft(centerX, toolbarWidth) {
|
|
|
18762
20586
|
function calcToolbarPos(rect, parentScroll, toolbarW = 306) {
|
|
18763
20587
|
const GAP = TOOLBAR_OFFSET_FROM_ELEMENT;
|
|
18764
20588
|
const APPROX_H = 32;
|
|
18765
|
-
const clip =
|
|
20589
|
+
const clip = getIframeChromeClip(parentScroll);
|
|
18766
20590
|
const clipTop = clip?.top ?? 0;
|
|
18767
20591
|
const canvasTopInIframe = parentScroll != null ? parentScroll.headerH - parentScroll.iframeOffsetTop : 0;
|
|
18768
20592
|
const visibleTop = rect.top - canvasTopInIframe;
|
|
@@ -18907,7 +20731,7 @@ function FloatingToolbar({
|
|
|
18907
20731
|
return () => ro.disconnect();
|
|
18908
20732
|
}, [showEditLink, activeCommands]);
|
|
18909
20733
|
const { top, left, transform } = calcToolbarPos(rect, parentScroll, measuredW);
|
|
18910
|
-
return /* @__PURE__ */ (0,
|
|
20734
|
+
return /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
|
|
18911
20735
|
"div",
|
|
18912
20736
|
{
|
|
18913
20737
|
ref: setRefs,
|
|
@@ -18919,12 +20743,12 @@ function FloatingToolbar({
|
|
|
18919
20743
|
zIndex: 2147483647,
|
|
18920
20744
|
pointerEvents: "auto"
|
|
18921
20745
|
},
|
|
18922
|
-
children: /* @__PURE__ */ (0,
|
|
18923
|
-
TOOLBAR_GROUPS.map((btns, gi) => /* @__PURE__ */ (0,
|
|
18924
|
-
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, {}),
|
|
18925
20749
|
btns.map((btn) => {
|
|
18926
20750
|
const isActive = activeCommands.has(btn.cmd);
|
|
18927
|
-
return /* @__PURE__ */ (0,
|
|
20751
|
+
return /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
|
|
18928
20752
|
CustomToolbarButton,
|
|
18929
20753
|
{
|
|
18930
20754
|
title: btn.title,
|
|
@@ -18933,7 +20757,7 @@ function FloatingToolbar({
|
|
|
18933
20757
|
e.preventDefault();
|
|
18934
20758
|
onCommand(btn.cmd);
|
|
18935
20759
|
},
|
|
18936
|
-
children: /* @__PURE__ */ (0,
|
|
20760
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
|
|
18937
20761
|
"svg",
|
|
18938
20762
|
{
|
|
18939
20763
|
width: "16",
|
|
@@ -18954,7 +20778,7 @@ function FloatingToolbar({
|
|
|
18954
20778
|
);
|
|
18955
20779
|
})
|
|
18956
20780
|
] }, gi)),
|
|
18957
|
-
showEditLink ? /* @__PURE__ */ (0,
|
|
20781
|
+
showEditLink ? /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
|
|
18958
20782
|
CustomToolbarButton,
|
|
18959
20783
|
{
|
|
18960
20784
|
type: "button",
|
|
@@ -18968,7 +20792,7 @@ function FloatingToolbar({
|
|
|
18968
20792
|
e.preventDefault();
|
|
18969
20793
|
e.stopPropagation();
|
|
18970
20794
|
},
|
|
18971
|
-
children: /* @__PURE__ */ (0,
|
|
20795
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(import_lucide_react20.Link, { className: "size-4 shrink-0", "aria-hidden": true })
|
|
18972
20796
|
}
|
|
18973
20797
|
) : null
|
|
18974
20798
|
] })
|
|
@@ -18985,7 +20809,7 @@ function StateToggle({
|
|
|
18985
20809
|
states,
|
|
18986
20810
|
onStateChange
|
|
18987
20811
|
}) {
|
|
18988
|
-
return /* @__PURE__ */ (0,
|
|
20812
|
+
return /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
|
|
18989
20813
|
ToggleGroup,
|
|
18990
20814
|
{
|
|
18991
20815
|
"data-ohw-state-toggle": "",
|
|
@@ -18999,11 +20823,12 @@ function StateToggle({
|
|
|
18999
20823
|
left: rect.right - 8,
|
|
19000
20824
|
transform: "translateX(-100%)"
|
|
19001
20825
|
},
|
|
19002
|
-
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))
|
|
19003
20827
|
}
|
|
19004
20828
|
);
|
|
19005
20829
|
}
|
|
19006
20830
|
var contentCache = /* @__PURE__ */ new Map();
|
|
20831
|
+
var fetchedContentPaths = /* @__PURE__ */ new Set();
|
|
19007
20832
|
var brandingCache = /* @__PURE__ */ new Map();
|
|
19008
20833
|
var OHW_LOADER_STYLE = {
|
|
19009
20834
|
position: "fixed",
|
|
@@ -19015,9 +20840,9 @@ var OHW_LOADER_STYLE = {
|
|
|
19015
20840
|
justifyContent: "center"
|
|
19016
20841
|
};
|
|
19017
20842
|
function OhwLoaderSpinner() {
|
|
19018
|
-
return /* @__PURE__ */ (0,
|
|
19019
|
-
/* @__PURE__ */ (0,
|
|
19020
|
-
/* @__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)(
|
|
19021
20846
|
"circle",
|
|
19022
20847
|
{
|
|
19023
20848
|
cx: "14",
|
|
@@ -19027,7 +20852,7 @@ function OhwLoaderSpinner() {
|
|
|
19027
20852
|
strokeWidth: "3",
|
|
19028
20853
|
strokeDasharray: "17 52",
|
|
19029
20854
|
strokeLinecap: "round",
|
|
19030
|
-
children: /* @__PURE__ */ (0,
|
|
20855
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
|
|
19031
20856
|
"animateTransform",
|
|
19032
20857
|
{
|
|
19033
20858
|
attributeName: "transform",
|
|
@@ -19043,7 +20868,7 @@ function OhwLoaderSpinner() {
|
|
|
19043
20868
|
] });
|
|
19044
20869
|
}
|
|
19045
20870
|
function OhwBrandMark() {
|
|
19046
|
-
return /* @__PURE__ */ (0,
|
|
20871
|
+
return /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)(
|
|
19047
20872
|
"svg",
|
|
19048
20873
|
{
|
|
19049
20874
|
width: "16",
|
|
@@ -19054,7 +20879,7 @@ function OhwBrandMark() {
|
|
|
19054
20879
|
style: { display: "block", flexShrink: 0 },
|
|
19055
20880
|
xmlns: "http://www.w3.org/2000/svg",
|
|
19056
20881
|
children: [
|
|
19057
|
-
/* @__PURE__ */ (0,
|
|
20882
|
+
/* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
|
|
19058
20883
|
"mask",
|
|
19059
20884
|
{
|
|
19060
20885
|
id: "ohw-badge-mark",
|
|
@@ -19064,15 +20889,15 @@ function OhwBrandMark() {
|
|
|
19064
20889
|
y: "0",
|
|
19065
20890
|
width: "48",
|
|
19066
20891
|
height: "48",
|
|
19067
|
-
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" })
|
|
19068
20893
|
}
|
|
19069
20894
|
),
|
|
19070
|
-
/* @__PURE__ */ (0,
|
|
19071
|
-
/* @__PURE__ */ (0,
|
|
19072
|
-
/* @__PURE__ */ (0,
|
|
19073
|
-
/* @__PURE__ */ (0,
|
|
19074
|
-
/* @__PURE__ */ (0,
|
|
19075
|
-
/* @__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" })
|
|
19076
20901
|
] })
|
|
19077
20902
|
]
|
|
19078
20903
|
}
|
|
@@ -19109,7 +20934,7 @@ var OHW_BADGE_LABEL_STYLE = {
|
|
|
19109
20934
|
whiteSpace: "nowrap"
|
|
19110
20935
|
};
|
|
19111
20936
|
function MadeWithOhhWells() {
|
|
19112
|
-
return /* @__PURE__ */ (0,
|
|
20937
|
+
return /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)(
|
|
19113
20938
|
"a",
|
|
19114
20939
|
{
|
|
19115
20940
|
href: "https://ohhwells.com",
|
|
@@ -19119,8 +20944,8 @@ function MadeWithOhhWells() {
|
|
|
19119
20944
|
"data-ohw-badge": "",
|
|
19120
20945
|
style: OHW_BADGE_STYLE,
|
|
19121
20946
|
children: [
|
|
19122
|
-
/* @__PURE__ */ (0,
|
|
19123
|
-
/* @__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" })
|
|
19124
20949
|
]
|
|
19125
20950
|
}
|
|
19126
20951
|
);
|
|
@@ -19607,13 +21432,6 @@ function OhhwellsBridge() {
|
|
|
19607
21432
|
const [isItemDragging, setIsItemDragging] = (0, import_react19.useState)(false);
|
|
19608
21433
|
const [isFooterFrameSelection, setIsFooterFrameSelection] = (0, import_react19.useState)(false);
|
|
19609
21434
|
isFooterFrameSelectionRef.current = isFooterFrameSelection;
|
|
19610
|
-
const [floatingPanel, setFloatingPanel] = (0, import_react19.useState)(null);
|
|
19611
|
-
const floatingPanelOpenRef = (0, import_react19.useRef)(false);
|
|
19612
|
-
floatingPanelOpenRef.current = floatingPanel !== null;
|
|
19613
|
-
const [floatingPanelPos, setFloatingPanelPos] = (0, import_react19.useState)(null);
|
|
19614
|
-
const [logoSizeDraft, setLogoSizeDraft] = (0, import_react19.useState)(null);
|
|
19615
|
-
const [editorViewport, setEditorViewport] = (0, import_react19.useState)("desktop");
|
|
19616
|
-
const [parentScrollSnap, setParentScrollSnap] = (0, import_react19.useState)(null);
|
|
19617
21435
|
const [navDropdownPreviewOpen, setNavDropdownPreviewOpen] = (0, import_react19.useState)(null);
|
|
19618
21436
|
const [footerHeadingVisible, setFooterHeadingVisible] = (0, import_react19.useState)(null);
|
|
19619
21437
|
const footerDragRef = (0, import_react19.useRef)(null);
|
|
@@ -19637,6 +21455,21 @@ function OhhwellsBridge() {
|
|
|
19637
21455
|
const stylesRef = (0, import_react19.useRef)("");
|
|
19638
21456
|
const appliedDrawerRef = (0, import_react19.useRef)(null);
|
|
19639
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);
|
|
19640
21473
|
const [sitePages, setSitePages] = (0, import_react19.useState)([]);
|
|
19641
21474
|
const [sectionsByPath, setSectionsByPath] = (0, import_react19.useState)({});
|
|
19642
21475
|
const sectionsPrefetchGenRef = (0, import_react19.useRef)(0);
|
|
@@ -19645,7 +21478,18 @@ function OhhwellsBridge() {
|
|
|
19645
21478
|
const linkPopoverOpenRef = (0, import_react19.useRef)(false);
|
|
19646
21479
|
const linkPopoverGraceUntilRef = (0, import_react19.useRef)(0);
|
|
19647
21480
|
setLinkPopoverRef.current = setLinkPopover;
|
|
21481
|
+
setFloatingPanelRef.current = setFloatingPanel;
|
|
19648
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
|
+
}, []);
|
|
19649
21493
|
(0, import_react19.useEffect)(() => {
|
|
19650
21494
|
setSectionOrderPersistHandler((entries) => {
|
|
19651
21495
|
const currentPath = window.location.pathname;
|
|
@@ -19911,6 +21755,7 @@ function OhhwellsBridge() {
|
|
|
19911
21755
|
hoveredItemElRef.current = null;
|
|
19912
21756
|
setHoveredItemRect(null);
|
|
19913
21757
|
setFloatingPanel(null);
|
|
21758
|
+
setFloatingPanelPos(null);
|
|
19914
21759
|
setLogoSizeDraft(null);
|
|
19915
21760
|
if (!activeElRef.current) {
|
|
19916
21761
|
if (nestedGroup?.isConnected) {
|
|
@@ -20511,6 +22356,47 @@ function OhhwellsBridge() {
|
|
|
20511
22356
|
},
|
|
20512
22357
|
[beginFooterDrag]
|
|
20513
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
|
+
}, []);
|
|
20514
22400
|
const handleItemDragStart = (0, import_react19.useCallback)(
|
|
20515
22401
|
(e) => {
|
|
20516
22402
|
const selected = selectedElRef.current;
|
|
@@ -20520,6 +22406,17 @@ function OhhwellsBridge() {
|
|
|
20520
22406
|
}
|
|
20521
22407
|
const clientX = e?.clientX ?? selected.getBoundingClientRect().left + 8;
|
|
20522
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
|
+
}
|
|
20523
22420
|
if (startFooterLinkDrag(selected, clientX, clientY, true)) return;
|
|
20524
22421
|
if (selected.hasAttribute("data-ohw-footer-col") || isInferredFooterGroup2(selected) && selected.closest("footer")) {
|
|
20525
22422
|
if (startFooterColumnDrag(selected, clientX, clientY, true)) return;
|
|
@@ -20529,10 +22426,15 @@ function OhhwellsBridge() {
|
|
|
20529
22426
|
setSiblingHintRect(null);
|
|
20530
22427
|
setIsItemDragging(true);
|
|
20531
22428
|
},
|
|
20532
|
-
[startFooterColumnDrag, startFooterLinkDrag, startNavLinkDrag]
|
|
22429
|
+
[startFooterColumnDrag, startFooterLinkDrag, startNavLinkDrag, refreshButtonDragVisuals]
|
|
20533
22430
|
);
|
|
20534
22431
|
const handleItemDragEnd = (0, import_react19.useCallback)(
|
|
20535
22432
|
(e) => {
|
|
22433
|
+
const collectionButton = buttonCollectionDragRef.current;
|
|
22434
|
+
if (collectionButton) {
|
|
22435
|
+
persistButtonCollectionDrag(collectionButton, e?.clientX);
|
|
22436
|
+
return;
|
|
22437
|
+
}
|
|
20536
22438
|
if (footerDragRef.current) {
|
|
20537
22439
|
const x = e?.clientX;
|
|
20538
22440
|
const y = e?.clientY;
|
|
@@ -20555,12 +22457,22 @@ function OhhwellsBridge() {
|
|
|
20555
22457
|
}
|
|
20556
22458
|
setIsItemDragging(false);
|
|
20557
22459
|
},
|
|
20558
|
-
[commitFooterDrag, commitNavDrag, navDragRef]
|
|
22460
|
+
[commitFooterDrag, commitNavDrag, navDragRef, persistButtonCollectionDrag]
|
|
20559
22461
|
);
|
|
20560
22462
|
const handleItemChromePointerDown = (0, import_react19.useCallback)((e) => {
|
|
20561
22463
|
if (e.button !== 0) return;
|
|
20562
22464
|
const selected = selectedElRef.current;
|
|
20563
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
|
+
}
|
|
20564
22476
|
const hrefKey = selected.getAttribute("data-ohw-href-key");
|
|
20565
22477
|
if (hrefKey && isFooterHrefKey(hrefKey)) {
|
|
20566
22478
|
footerPointerDragRef.current = {
|
|
@@ -20639,10 +22551,29 @@ function OhhwellsBridge() {
|
|
|
20639
22551
|
setIsFooterFrameSelection(false);
|
|
20640
22552
|
setToolbarVariant("link-action");
|
|
20641
22553
|
setToolbarRect(anchor.getBoundingClientRect());
|
|
22554
|
+
if (glowElRef.current) glowElRef.current.style.display = "";
|
|
20642
22555
|
setToolbarShowEditLink(false);
|
|
20643
22556
|
setActiveCommands(/* @__PURE__ */ new Set());
|
|
20644
|
-
|
|
20645
|
-
|
|
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
|
+
}
|
|
20646
22577
|
}, [deactivate, markSelected]);
|
|
20647
22578
|
const selectFrame = (0, import_react19.useCallback)((el) => {
|
|
20648
22579
|
if (!isNavigationContainer(el)) return;
|
|
@@ -20682,6 +22613,7 @@ function OhhwellsBridge() {
|
|
|
20682
22613
|
setToolbarShowEditLink(false);
|
|
20683
22614
|
setActiveCommands(/* @__PURE__ */ new Set());
|
|
20684
22615
|
setFloatingPanel(null);
|
|
22616
|
+
setFloatingPanelPos(null);
|
|
20685
22617
|
setLogoSizeDraft(null);
|
|
20686
22618
|
}, [deactivate, markSelected, postToParent2]);
|
|
20687
22619
|
const selectLogo = (0, import_react19.useCallback)(
|
|
@@ -20727,6 +22659,7 @@ function OhhwellsBridge() {
|
|
|
20727
22659
|
});
|
|
20728
22660
|
}, []);
|
|
20729
22661
|
const openSocialsDisplayPanel = (0, import_react19.useCallback)((row) => {
|
|
22662
|
+
setFloatingPanelPos(null);
|
|
20730
22663
|
setParentScrollSnap(parentScrollRef.current);
|
|
20731
22664
|
setFloatingPanel({
|
|
20732
22665
|
key: "socials-display",
|
|
@@ -20736,6 +22669,87 @@ function OhhwellsBridge() {
|
|
|
20736
22669
|
row
|
|
20737
22670
|
});
|
|
20738
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]);
|
|
20739
22753
|
const isEditModeRef = (0, import_react19.useRef)(false);
|
|
20740
22754
|
const requestMissingSocialIconsRef = (0, import_react19.useRef)(() => {
|
|
20741
22755
|
});
|
|
@@ -20778,11 +22792,13 @@ function OhhwellsBridge() {
|
|
|
20778
22792
|
);
|
|
20779
22793
|
const closeFloatingPanelOnly = (0, import_react19.useCallback)(() => {
|
|
20780
22794
|
setFloatingPanel(null);
|
|
22795
|
+
setFloatingPanelPos(null);
|
|
20781
22796
|
setLogoSizeDraft(null);
|
|
20782
22797
|
}, []);
|
|
20783
22798
|
closeFloatingPanelOnlyRef.current = closeFloatingPanelOnly;
|
|
20784
22799
|
const closeFloatingPanelAndDeselect = (0, import_react19.useCallback)(() => {
|
|
20785
22800
|
setFloatingPanel(null);
|
|
22801
|
+
setFloatingPanelPos(null);
|
|
20786
22802
|
setLogoSizeDraft(null);
|
|
20787
22803
|
deselectRef.current();
|
|
20788
22804
|
}, []);
|
|
@@ -20991,18 +23007,21 @@ function OhhwellsBridge() {
|
|
|
20991
23007
|
}
|
|
20992
23008
|
if (typeof content[STYLE_STORE_KEY] === "string") {
|
|
20993
23009
|
stylesRef.current = content[STYLE_STORE_KEY];
|
|
23010
|
+
document.querySelectorAll('[data-ohw-editable="form"]').forEach((f) => markFormFields(f));
|
|
20994
23011
|
applyStylesToDom(parseStyleStore(content[STYLE_STORE_KEY]));
|
|
20995
23012
|
}
|
|
20996
23013
|
applyBrandChrome(content);
|
|
23014
|
+
applyCustomCodeToHead(content);
|
|
20997
23015
|
initSectionInstancesFromContent(content, window.location.pathname);
|
|
20998
23016
|
for (const [key, val] of Object.entries(content)) {
|
|
20999
23017
|
if (key === "__ohw_sections") continue;
|
|
21000
23018
|
if (key === AI_SECTIONS_KEY) continue;
|
|
23019
|
+
if (key === LOGO_PLACEHOLDER_KEY) continue;
|
|
23020
|
+
if (LOGO_IMAGE_KEYS.includes(key)) continue;
|
|
21001
23021
|
if (key === BRAND_KIT_KEY) continue;
|
|
21002
23022
|
if (key === STYLE_STORE_KEY) continue;
|
|
21003
23023
|
if (BRAND_CHROME_KEYS.has(key)) continue;
|
|
21004
|
-
if (key ===
|
|
21005
|
-
if (LOGO_IMAGE_KEYS.includes(key)) continue;
|
|
23024
|
+
if (key === CUSTOM_CODE_AFTER_HEAD_KEY || key === CUSTOM_CODE_BEFORE_HEAD_KEY) continue;
|
|
21006
23025
|
if (applyVideoSettingNode(key, val)) continue;
|
|
21007
23026
|
if (applyCarouselNode(key, val)) continue;
|
|
21008
23027
|
document.querySelectorAll(`[data-ohw-key="${key}"]`).forEach((el) => {
|
|
@@ -21049,6 +23068,7 @@ function OhhwellsBridge() {
|
|
|
21049
23068
|
reconcileSocialsFromContent(content);
|
|
21050
23069
|
applySocialsDisplayFromContent(content);
|
|
21051
23070
|
applySocialsLabelsFromContent(content, document, { fillEmptyOnly: isEditModeRef.current });
|
|
23071
|
+
syncButtonsFromContent(document, content);
|
|
21052
23072
|
if (isEditModeRef.current) requestMissingSocialIconsRef.current();
|
|
21053
23073
|
if (typeof content[STYLE_STORE_KEY] === "string") {
|
|
21054
23074
|
applyStylesToDom(parseStyleStore(content[STYLE_STORE_KEY]));
|
|
@@ -21073,7 +23093,9 @@ function OhhwellsBridge() {
|
|
|
21073
23093
|
let cancelled = false;
|
|
21074
23094
|
setFetchState("loading");
|
|
21075
23095
|
const apiUrl = process.env.NEXT_PUBLIC_FLOWOPS_API_URL ?? "https://flowops-backend-staging-2yfdh7pwpq-as.a.run.app";
|
|
21076
|
-
|
|
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) => {
|
|
21077
23099
|
if (cancelled) return;
|
|
21078
23100
|
const content = data?.content ?? {};
|
|
21079
23101
|
const branding = Boolean(data?.showBranding);
|
|
@@ -21209,16 +23231,17 @@ function OhhwellsBridge() {
|
|
|
21209
23231
|
applyAiSectionsToDom(parseAiSectionsState(content[AI_SECTIONS_KEY]));
|
|
21210
23232
|
}
|
|
21211
23233
|
if (typeof content[STYLE_STORE_KEY] === "string") {
|
|
23234
|
+
document.querySelectorAll('[data-ohw-editable="form"]').forEach((f) => markFormFields(f));
|
|
21212
23235
|
applyStylesToDom(parseStyleStore(content[STYLE_STORE_KEY]));
|
|
21213
23236
|
}
|
|
21214
23237
|
for (const [key, val] of Object.entries(content)) {
|
|
21215
23238
|
if (key === "__ohw_sections") continue;
|
|
21216
23239
|
if (key === AI_SECTIONS_KEY) continue;
|
|
23240
|
+
if (key === LOGO_PLACEHOLDER_KEY) continue;
|
|
23241
|
+
if (LOGO_IMAGE_KEYS.includes(key)) continue;
|
|
21217
23242
|
if (key === BRAND_KIT_KEY) continue;
|
|
21218
23243
|
if (key === STYLE_STORE_KEY) continue;
|
|
21219
23244
|
if (BRAND_CHROME_KEYS.has(key)) continue;
|
|
21220
|
-
if (key === LOGO_PLACEHOLDER_KEY) continue;
|
|
21221
|
-
if (LOGO_IMAGE_KEYS.includes(key)) continue;
|
|
21222
23245
|
if (applyVideoSettingNode(key, val)) continue;
|
|
21223
23246
|
if (applyCarouselNode(key, val)) continue;
|
|
21224
23247
|
document.querySelectorAll(`[data-ohw-key="${key}"]`).forEach((el) => {
|
|
@@ -21249,6 +23272,7 @@ function OhhwellsBridge() {
|
|
|
21249
23272
|
reconcileSocialsFromContent(content);
|
|
21250
23273
|
applySocialsDisplayFromContent(content);
|
|
21251
23274
|
applySocialsLabelsFromContent(content, document, { fillEmptyOnly: isEditModeRef.current });
|
|
23275
|
+
syncButtonsFromContent(document, content);
|
|
21252
23276
|
if (isEditModeRef.current) requestMissingSocialIconsRef.current();
|
|
21253
23277
|
if (typeof content[STYLE_STORE_KEY] === "string") {
|
|
21254
23278
|
applyStylesToDom(parseStyleStore(content[STYLE_STORE_KEY]));
|
|
@@ -21269,6 +23293,17 @@ function OhhwellsBridge() {
|
|
|
21269
23293
|
debounceTimer = setTimeout(applyFromCache, 150);
|
|
21270
23294
|
};
|
|
21271
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
|
+
}
|
|
21272
23307
|
observer = new MutationObserver(scheduleApply);
|
|
21273
23308
|
observer.observe(document.body, { childList: true, subtree: true });
|
|
21274
23309
|
return () => {
|
|
@@ -21337,7 +23372,10 @@ function OhhwellsBridge() {
|
|
|
21337
23372
|
if (roots.length === 0) {
|
|
21338
23373
|
reconcileNavbarItemsFromContent(contentForNav());
|
|
21339
23374
|
reconcileFooterOrderFromContent(contentForNav());
|
|
21340
|
-
if (isEditMode)
|
|
23375
|
+
if (isEditMode) {
|
|
23376
|
+
syncButtonsFromContent(document, contentForNav());
|
|
23377
|
+
syncNavigationDragCursorAttrs();
|
|
23378
|
+
}
|
|
21341
23379
|
return;
|
|
21342
23380
|
}
|
|
21343
23381
|
let rafId = null;
|
|
@@ -21349,7 +23387,7 @@ function OhhwellsBridge() {
|
|
|
21349
23387
|
}
|
|
21350
23388
|
};
|
|
21351
23389
|
const run = () => {
|
|
21352
|
-
if (footerDragRef.current || navDragRef.current || applying) return;
|
|
23390
|
+
if (footerDragRef.current || navDragRef.current || buttonCollectionDragRef.current || applying) return;
|
|
21353
23391
|
applying = true;
|
|
21354
23392
|
observer?.disconnect();
|
|
21355
23393
|
try {
|
|
@@ -21359,6 +23397,7 @@ function OhhwellsBridge() {
|
|
|
21359
23397
|
reconcileSocialsFromContent(content);
|
|
21360
23398
|
applySocialsDisplayFromContent(content);
|
|
21361
23399
|
applySocialsLabelsFromContent(content, document, { fillEmptyOnly: isEditModeRef.current });
|
|
23400
|
+
syncButtonsFromContent(document, content);
|
|
21362
23401
|
if (isEditModeRef.current) requestMissingSocialIconsRef.current();
|
|
21363
23402
|
document.querySelectorAll("footer [data-ohw-href-key]").forEach((el) => {
|
|
21364
23403
|
if (isFooterHrefKey(el.getAttribute("data-ohw-href-key")) || getSocialItem(el)) {
|
|
@@ -21366,9 +23405,9 @@ function OhhwellsBridge() {
|
|
|
21366
23405
|
}
|
|
21367
23406
|
});
|
|
21368
23407
|
document.querySelectorAll(
|
|
21369
|
-
|
|
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"]'
|
|
21370
23409
|
).forEach((el) => {
|
|
21371
|
-
if (isNavbarHrefKey(el.getAttribute("data-ohw-href-key"))) {
|
|
23410
|
+
if (isNavbarHrefKey(el.getAttribute("data-ohw-href-key")) || isCtaButton(el)) {
|
|
21372
23411
|
disableNativeHrefDrag(el);
|
|
21373
23412
|
}
|
|
21374
23413
|
});
|
|
@@ -21393,6 +23432,44 @@ function OhhwellsBridge() {
|
|
|
21393
23432
|
observer?.disconnect();
|
|
21394
23433
|
};
|
|
21395
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]);
|
|
21396
23473
|
(0, import_react19.useEffect)(() => {
|
|
21397
23474
|
if (!isEditMode) return;
|
|
21398
23475
|
let lastPosted = 0;
|
|
@@ -21415,26 +23492,11 @@ function OhhwellsBridge() {
|
|
|
21415
23492
|
const t2 = setTimeout(measure, 500);
|
|
21416
23493
|
const ro = new ResizeObserver(schedule);
|
|
21417
23494
|
ro.observe(document.body);
|
|
21418
|
-
let lastWidth = window.innerWidth;
|
|
21419
|
-
let resizeTimers = [];
|
|
21420
|
-
const clearResizeTimers = () => {
|
|
21421
|
-
resizeTimers.forEach(clearTimeout);
|
|
21422
|
-
resizeTimers = [];
|
|
21423
|
-
};
|
|
21424
|
-
const handleResize = () => {
|
|
21425
|
-
if (window.innerWidth === lastWidth) return;
|
|
21426
|
-
lastWidth = window.innerWidth;
|
|
21427
|
-
clearResizeTimers();
|
|
21428
|
-
resizeTimers = HEIGHT_SETTLE_DELAYS.map((delay) => setTimeout(measure, delay));
|
|
21429
|
-
};
|
|
21430
|
-
window.addEventListener("resize", handleResize);
|
|
21431
23495
|
return () => {
|
|
21432
23496
|
clearTimeout(t1);
|
|
21433
23497
|
clearTimeout(t2);
|
|
21434
23498
|
if (raf != null) cancelAnimationFrame(raf);
|
|
21435
23499
|
ro.disconnect();
|
|
21436
|
-
clearResizeTimers();
|
|
21437
|
-
window.removeEventListener("resize", handleResize);
|
|
21438
23500
|
};
|
|
21439
23501
|
}, [pathname, isEditMode, postToParent2]);
|
|
21440
23502
|
(0, import_react19.useEffect)(() => {
|
|
@@ -21729,6 +23791,13 @@ function OhhwellsBridge() {
|
|
|
21729
23791
|
if (target.closest("[data-ohw-state-toggle]")) return;
|
|
21730
23792
|
if (target.closest("[data-ohw-max-badge]")) return;
|
|
21731
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
|
+
}
|
|
21732
23801
|
if (selectedMediaElRef.current && !selectedMediaElRef.current.contains(target) && !target.closest("[data-ohw-media-overlay], [data-ohw-edit-chrome], [data-ohw-item-interaction]")) {
|
|
21733
23802
|
clearMediaSelectionRef.current();
|
|
21734
23803
|
}
|
|
@@ -21749,13 +23818,6 @@ function OhhwellsBridge() {
|
|
|
21749
23818
|
return;
|
|
21750
23819
|
}
|
|
21751
23820
|
}
|
|
21752
|
-
if (isInsideFloatingPanel(target)) return;
|
|
21753
|
-
if (target.closest("[data-ohw-form-toolbar]")) return;
|
|
21754
|
-
if (target.closest(
|
|
21755
|
-
'[data-ohw-field-toolbar], [data-ohw-field-type-picker], [data-radix-popper-content-wrapper], [role="menu"], [data-slot="dropdown-menu-content"]'
|
|
21756
|
-
)) {
|
|
21757
|
-
return;
|
|
21758
|
-
}
|
|
21759
23821
|
{
|
|
21760
23822
|
const formEl = getFormElement(target);
|
|
21761
23823
|
const onSuccessText = target.closest(`[${SUCCESS_TEXT_ATTR}]`);
|
|
@@ -21919,14 +23981,6 @@ function OhhwellsBridge() {
|
|
|
21919
23981
|
}
|
|
21920
23982
|
const clickedButton = findClosestButtonLike(target);
|
|
21921
23983
|
const buttonOnMedia = Boolean(clickedButton && isMediaEditable(editable) && editable.contains(clickedButton));
|
|
21922
|
-
console.log("[click-debug]", {
|
|
21923
|
-
editableType: editable.dataset.ohwEditable,
|
|
21924
|
-
editableTag: editable.tagName,
|
|
21925
|
-
targetTag: target.tagName,
|
|
21926
|
-
clickedButtonTag: clickedButton?.tagName ?? null,
|
|
21927
|
-
buttonOnMedia,
|
|
21928
|
-
isMediaEditableEditable: isMediaEditable(editable)
|
|
21929
|
-
});
|
|
21930
23984
|
if (isMediaEditable(editable) && !buttonOnMedia) {
|
|
21931
23985
|
e.preventDefault();
|
|
21932
23986
|
e.stopPropagation();
|
|
@@ -21961,11 +24015,6 @@ function OhhwellsBridge() {
|
|
|
21961
24015
|
const hrefLookupTarget = buttonOnMedia ? clickedButton : editable;
|
|
21962
24016
|
const hrefCtx = getHrefKeyFromElement(hrefLookupTarget);
|
|
21963
24017
|
const navAnchor = hrefCtx ? getNavigationItemAnchor(hrefCtx.anchor) : null;
|
|
21964
|
-
console.log("[click-debug 2]", {
|
|
21965
|
-
hrefLookupTargetTag: hrefLookupTarget.tagName,
|
|
21966
|
-
hrefCtx: hrefCtx ? { key: hrefCtx.key } : null,
|
|
21967
|
-
navAnchorTag: navAnchor?.tagName ?? null
|
|
21968
|
-
});
|
|
21969
24018
|
if (navAnchor) {
|
|
21970
24019
|
e.preventDefault();
|
|
21971
24020
|
e.stopPropagation();
|
|
@@ -22148,6 +24197,9 @@ function OhhwellsBridge() {
|
|
|
22148
24197
|
setHoveredItemRect(null);
|
|
22149
24198
|
hoveredNavContainerRef.current = null;
|
|
22150
24199
|
setHoveredNavContainerRect(null);
|
|
24200
|
+
siblingHintElRef.current = null;
|
|
24201
|
+
setSiblingHintRect(null);
|
|
24202
|
+
setSiblingHintRects([]);
|
|
22151
24203
|
return;
|
|
22152
24204
|
}
|
|
22153
24205
|
{
|
|
@@ -22268,7 +24320,6 @@ function OhhwellsBridge() {
|
|
|
22268
24320
|
hoveredNavContainerRef.current = null;
|
|
22269
24321
|
setHoveredNavContainerRect(null);
|
|
22270
24322
|
hoveredItemElRef.current = editable;
|
|
22271
|
-
setHoveredItemRect(isSelectedForHoverRef.current(editable) ? null : editable.getBoundingClientRect());
|
|
22272
24323
|
}
|
|
22273
24324
|
}
|
|
22274
24325
|
}
|
|
@@ -22481,6 +24532,20 @@ function OhhwellsBridge() {
|
|
|
22481
24532
|
}
|
|
22482
24533
|
return;
|
|
22483
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
|
+
}
|
|
22484
24549
|
const navContainers = Array.from(
|
|
22485
24550
|
document.querySelectorAll("[data-ohw-nav-container]")
|
|
22486
24551
|
);
|
|
@@ -22572,7 +24637,7 @@ function OhhwellsBridge() {
|
|
|
22572
24637
|
};
|
|
22573
24638
|
const probeImageAt = (clientX, clientY, isDragOver = false, fromParentViewport = false) => {
|
|
22574
24639
|
syncSelectedMediaPointerRelease(true);
|
|
22575
|
-
if (linkPopoverOpenRef.current) {
|
|
24640
|
+
if (linkPopoverOpenRef.current || floatingPanelOpenRef.current && isPointOverFloatingPanel(clientX, clientY)) {
|
|
22576
24641
|
if (hoveredImageRef.current) {
|
|
22577
24642
|
hoveredImageRef.current = null;
|
|
22578
24643
|
hoveredImageHasTextOverlapRef.current = false;
|
|
@@ -22583,6 +24648,24 @@ function OhhwellsBridge() {
|
|
|
22583
24648
|
return;
|
|
22584
24649
|
}
|
|
22585
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
|
+
}
|
|
22586
24669
|
if (isPointOverNavigation(x, y)) {
|
|
22587
24670
|
dismissImageHover();
|
|
22588
24671
|
probeNavigationHoverAt(x, y);
|
|
@@ -22946,7 +25029,11 @@ function OhhwellsBridge() {
|
|
|
22946
25029
|
};
|
|
22947
25030
|
const handleMouseMove = (e) => {
|
|
22948
25031
|
const { clientX, clientY } = e;
|
|
22949
|
-
if (pointOwnedByFloatingPanel(clientX, clientY))
|
|
25032
|
+
if (pointOwnedByFloatingPanel(clientX, clientY)) {
|
|
25033
|
+
dismissImageHover();
|
|
25034
|
+
clearImageHover();
|
|
25035
|
+
return;
|
|
25036
|
+
}
|
|
22950
25037
|
if (isNavDrawerOpen() && isPointOutsideOpenDrawer(clientX, clientY)) {
|
|
22951
25038
|
document.querySelectorAll("[data-ohw-hovered]").forEach((el) => el.removeAttribute("data-ohw-hovered"));
|
|
22952
25039
|
formHoverElRef.current = null;
|
|
@@ -22975,7 +25062,12 @@ function OhhwellsBridge() {
|
|
|
22975
25062
|
setHoveredItemRect(null);
|
|
22976
25063
|
hoveredNavContainerRef.current = null;
|
|
22977
25064
|
setHoveredNavContainerRect(null);
|
|
25065
|
+
siblingHintElRef.current = null;
|
|
25066
|
+
setSiblingHintRect(null);
|
|
25067
|
+
setSiblingHintRects([]);
|
|
22978
25068
|
dismissImageHover();
|
|
25069
|
+
clearImageHover();
|
|
25070
|
+
setSectionGap(null);
|
|
22979
25071
|
return;
|
|
22980
25072
|
}
|
|
22981
25073
|
if (probeSocialsRowAt(clientX, clientY)) return;
|
|
@@ -22987,7 +25079,11 @@ function OhhwellsBridge() {
|
|
|
22987
25079
|
if (e.data?.type !== "ow:pointer-sync") return;
|
|
22988
25080
|
const { clientX, clientY } = e.data;
|
|
22989
25081
|
if (typeof clientX !== "number" || typeof clientY !== "number") return;
|
|
22990
|
-
if (pointOwnedByFloatingPanel(clientX, clientY))
|
|
25082
|
+
if (pointOwnedByFloatingPanel(clientX, clientY)) {
|
|
25083
|
+
dismissImageHover();
|
|
25084
|
+
clearImageHover();
|
|
25085
|
+
return;
|
|
25086
|
+
}
|
|
22991
25087
|
if (isNavDrawerOpen() && isPointOutsideOpenDrawer(clientX, clientY)) return;
|
|
22992
25088
|
if (probeSocialsRowAt(clientX, clientY)) return;
|
|
22993
25089
|
probeSectionGapAt(clientX, clientY);
|
|
@@ -23004,6 +25100,11 @@ function OhhwellsBridge() {
|
|
|
23004
25100
|
return;
|
|
23005
25101
|
}
|
|
23006
25102
|
if (onNavDragOver(e)) return;
|
|
25103
|
+
if (buttonCollectionDragRef.current) {
|
|
25104
|
+
e.preventDefault();
|
|
25105
|
+
if (e.dataTransfer) e.dataTransfer.dropEffect = "move";
|
|
25106
|
+
return;
|
|
25107
|
+
}
|
|
23007
25108
|
e.preventDefault();
|
|
23008
25109
|
const el = findImageAtPoint(e.clientX, e.clientY, false);
|
|
23009
25110
|
if (!el) {
|
|
@@ -23028,6 +25129,7 @@ function OhhwellsBridge() {
|
|
|
23028
25129
|
};
|
|
23029
25130
|
const handleDrop = (e) => {
|
|
23030
25131
|
e.preventDefault();
|
|
25132
|
+
if (buttonCollectionDragRef.current || navDragRef.current || footerDragRef.current) return;
|
|
23031
25133
|
const el = findImageAtPoint(e.clientX, e.clientY, false);
|
|
23032
25134
|
if (!el) return;
|
|
23033
25135
|
const file = e.dataTransfer?.files?.[0];
|
|
@@ -23327,9 +25429,11 @@ function OhhwellsBridge() {
|
|
|
23327
25429
|
}
|
|
23328
25430
|
if (typeof content[STYLE_STORE_KEY] === "string") {
|
|
23329
25431
|
stylesRef.current = content[STYLE_STORE_KEY];
|
|
25432
|
+
document.querySelectorAll('[data-ohw-editable="form"]').forEach((f) => markFormFields(f));
|
|
23330
25433
|
applyStylesToDom(parseStyleStore(content[STYLE_STORE_KEY]));
|
|
23331
25434
|
}
|
|
23332
25435
|
applyBrandChrome(content);
|
|
25436
|
+
applyCustomCodeToHead(content);
|
|
23333
25437
|
initSectionInstancesFromContent(content, window.location.pathname);
|
|
23334
25438
|
let sectionsJson = null;
|
|
23335
25439
|
for (const [key, val] of Object.entries(content)) {
|
|
@@ -23338,11 +25442,12 @@ function OhhwellsBridge() {
|
|
|
23338
25442
|
continue;
|
|
23339
25443
|
}
|
|
23340
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;
|
|
23341
25447
|
if (key === BRAND_KIT_KEY) continue;
|
|
23342
25448
|
if (key === STYLE_STORE_KEY) continue;
|
|
23343
25449
|
if (BRAND_CHROME_KEYS.has(key)) continue;
|
|
23344
|
-
if (key ===
|
|
23345
|
-
if (LOGO_IMAGE_KEYS.includes(key) && !String(val ?? "").trim()) continue;
|
|
25450
|
+
if (key === CUSTOM_CODE_AFTER_HEAD_KEY || key === CUSTOM_CODE_BEFORE_HEAD_KEY) continue;
|
|
23346
25451
|
if (applyVideoSettingNode(key, val)) continue;
|
|
23347
25452
|
if (applyCarouselNode(key, val)) continue;
|
|
23348
25453
|
document.querySelectorAll(`[data-ohw-key="${key}"]`).forEach((el) => {
|
|
@@ -23381,6 +25486,7 @@ function OhhwellsBridge() {
|
|
|
23381
25486
|
editContentRef.current = { ...editContentRef.current, ...content };
|
|
23382
25487
|
reconcileNavbarItemsFromContent(editContentRef.current);
|
|
23383
25488
|
reconcileFooterOrderFromContent(editContentRef.current);
|
|
25489
|
+
syncButtonsFromContent(document, editContentRef.current);
|
|
23384
25490
|
syncNavigationDragCursorAttrs();
|
|
23385
25491
|
if (typeof content[STYLE_STORE_KEY] === "string") {
|
|
23386
25492
|
applyStylesToDom(parseStyleStore(content[STYLE_STORE_KEY]));
|
|
@@ -23787,6 +25893,12 @@ function OhhwellsBridge() {
|
|
|
23787
25893
|
closeLinkPopoverRef.current();
|
|
23788
25894
|
return;
|
|
23789
25895
|
}
|
|
25896
|
+
if (floatingPanelOpenRef.current) {
|
|
25897
|
+
setFloatingPanelRef.current(null);
|
|
25898
|
+
deselectRef.current();
|
|
25899
|
+
deactivateRef.current();
|
|
25900
|
+
return;
|
|
25901
|
+
}
|
|
23790
25902
|
deselectRef.current();
|
|
23791
25903
|
deactivateRef.current();
|
|
23792
25904
|
clearMediaSelectionRef.current();
|
|
@@ -24053,6 +26165,16 @@ function OhhwellsBridge() {
|
|
|
24053
26165
|
if (brandKitRef.current) {
|
|
24054
26166
|
nodes.push({ key: BRAND_KIT_KEY, type: "brand", text: brandKitRef.current });
|
|
24055
26167
|
}
|
|
26168
|
+
nodes.push({
|
|
26169
|
+
key: CUSTOM_CODE_BEFORE_HEAD_KEY,
|
|
26170
|
+
type: "text",
|
|
26171
|
+
text: editContentRef.current[CUSTOM_CODE_BEFORE_HEAD_KEY] ?? ""
|
|
26172
|
+
});
|
|
26173
|
+
nodes.push({
|
|
26174
|
+
key: CUSTOM_CODE_AFTER_HEAD_KEY,
|
|
26175
|
+
type: "text",
|
|
26176
|
+
text: editContentRef.current[CUSTOM_CODE_AFTER_HEAD_KEY] ?? ""
|
|
26177
|
+
});
|
|
24056
26178
|
document.querySelectorAll('[data-ohw-editable="form"]').forEach((form) => {
|
|
24057
26179
|
const formKey = formKeyOf(form);
|
|
24058
26180
|
if (!formKey) return;
|
|
@@ -24075,8 +26197,12 @@ function OhhwellsBridge() {
|
|
|
24075
26197
|
if (inserted) {
|
|
24076
26198
|
const tracker = getSectionsTracker();
|
|
24077
26199
|
postToParentRef.current({ type: "ow:change", nodes: [{ key: "__ohw_sections", text: tracker.textContent ?? "[]" }] });
|
|
24078
|
-
const
|
|
24079
|
-
|
|
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);
|
|
24080
26206
|
}
|
|
24081
26207
|
};
|
|
24082
26208
|
const handleSwitchSchedule = (e) => {
|
|
@@ -24280,11 +26406,8 @@ function OhhwellsBridge() {
|
|
|
24280
26406
|
};
|
|
24281
26407
|
const handleParentScroll = (e) => {
|
|
24282
26408
|
if (e.data?.type !== "ow:parent-scroll") return;
|
|
24283
|
-
const { iframeOffsetTop, headerH, canvasH } = e.data;
|
|
24284
|
-
parentScrollRef.current = { iframeOffsetTop, headerH, canvasH };
|
|
24285
|
-
if (floatingPanelOpenRef.current) {
|
|
24286
|
-
setParentScrollSnap({ iframeOffsetTop, headerH, canvasH });
|
|
24287
|
-
}
|
|
26409
|
+
const { iframeOffsetTop, headerH, canvasH, promptBarH = 0 } = e.data;
|
|
26410
|
+
parentScrollRef.current = { iframeOffsetTop, headerH, canvasH, promptBarH };
|
|
24288
26411
|
if (visibleViewportRef.current) {
|
|
24289
26412
|
applyVisibleViewport(visibleViewportRef.current, parentScrollRef.current);
|
|
24290
26413
|
}
|
|
@@ -24508,10 +26631,10 @@ function OhhwellsBridge() {
|
|
|
24508
26631
|
window.removeEventListener("message", handleDeleteSection);
|
|
24509
26632
|
window.removeEventListener("message", handleDuplicateSection);
|
|
24510
26633
|
window.removeEventListener("message", handleDeactivate);
|
|
24511
|
-
document.documentElement.removeAttribute("data-ohw-panel-dragging");
|
|
24512
26634
|
window.removeEventListener("message", handleToastAction);
|
|
24513
26635
|
window.removeEventListener("message", handleFormCount);
|
|
24514
26636
|
window.removeEventListener("message", handleUiEscape);
|
|
26637
|
+
document.documentElement.removeAttribute("data-ohw-panel-dragging");
|
|
24515
26638
|
autoSaveTimers.current.forEach(clearTimeout);
|
|
24516
26639
|
autoSaveTimers.current.clear();
|
|
24517
26640
|
if (imageUnhoverTimerRef.current) clearTimeout(imageUnhoverTimerRef.current);
|
|
@@ -24674,6 +26797,97 @@ function OhhwellsBridge() {
|
|
|
24674
26797
|
unlockFooterDragInteraction();
|
|
24675
26798
|
};
|
|
24676
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]);
|
|
24677
26891
|
(0, import_react19.useEffect)(() => {
|
|
24678
26892
|
const handler = (e) => {
|
|
24679
26893
|
if (e.data?.type !== "ow:request-schedule-config") return;
|
|
@@ -24714,7 +26928,7 @@ function OhhwellsBridge() {
|
|
|
24714
26928
|
postToParent2({
|
|
24715
26929
|
type: "ow:ready",
|
|
24716
26930
|
version: "1",
|
|
24717
|
-
bridgeVersion: "0.1.
|
|
26931
|
+
bridgeVersion: "0.1.122",
|
|
24718
26932
|
path: pathname,
|
|
24719
26933
|
nodes: collectEditableNodes(editContentRef.current),
|
|
24720
26934
|
sections
|
|
@@ -24793,12 +27007,12 @@ function OhhwellsBridge() {
|
|
|
24793
27007
|
return;
|
|
24794
27008
|
}
|
|
24795
27009
|
if (type !== "ow:logo-size-set") return;
|
|
24796
|
-
const
|
|
24797
|
-
if (!Number.isFinite(
|
|
24798
|
-
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 } : {
|
|
24799
27013
|
...logoSizeDraft,
|
|
24800
|
-
desktopPx:
|
|
24801
|
-
mobilePx: logoSizeDraft.mobileFollowing ?
|
|
27014
|
+
desktopPx: px2,
|
|
27015
|
+
mobilePx: logoSizeDraft.mobileFollowing ? px2 : logoSizeDraft.mobilePx
|
|
24802
27016
|
};
|
|
24803
27017
|
setLogoSizeDraft(next);
|
|
24804
27018
|
persistLogoSizeDraft(session.placement, next);
|
|
@@ -24896,6 +27110,36 @@ function OhhwellsBridge() {
|
|
|
24896
27110
|
const handleDuplicateSelected = (0, import_react19.useCallback)(() => {
|
|
24897
27111
|
const selected = selectedElRef.current;
|
|
24898
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
|
+
}
|
|
24899
27143
|
const hrefKey = selected.getAttribute("data-ohw-href-key");
|
|
24900
27144
|
if (!hrefKey) return;
|
|
24901
27145
|
const social = getSocialItem(selected);
|
|
@@ -25025,7 +27269,7 @@ function OhhwellsBridge() {
|
|
|
25025
27269
|
selectRef.current(result.anchor);
|
|
25026
27270
|
});
|
|
25027
27271
|
}
|
|
25028
|
-
}, [postToParent2]);
|
|
27272
|
+
}, [postToParent2, tokensForButton]);
|
|
25029
27273
|
const runPendingDeleteUndo = (0, import_react19.useCallback)(() => {
|
|
25030
27274
|
const pending = pendingDeleteUndoRef.current;
|
|
25031
27275
|
if (!pending) return false;
|
|
@@ -25037,6 +27281,38 @@ function OhhwellsBridge() {
|
|
|
25037
27281
|
const handleDeleteSelected = (0, import_react19.useCallback)(() => {
|
|
25038
27282
|
const selected = selectedElRef.current;
|
|
25039
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
|
+
}
|
|
25040
27316
|
return deleteSelectedNavFooterItem({
|
|
25041
27317
|
selected,
|
|
25042
27318
|
isTextEditing: Boolean(activeElRef.current),
|
|
@@ -25174,14 +27450,14 @@ function OhhwellsBridge() {
|
|
|
25174
27450
|
},
|
|
25175
27451
|
[postToParent2]
|
|
25176
27452
|
);
|
|
25177
|
-
return /* @__PURE__ */ (0,
|
|
25178
|
-
/* @__PURE__ */ (0,
|
|
25179
|
-
/* @__PURE__ */ (0,
|
|
25180
|
-
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, {}),
|
|
25181
27457
|
bridgeRoot ? (0, import_react_dom5.createPortal)(
|
|
25182
|
-
/* @__PURE__ */ (0,
|
|
25183
|
-
/* @__PURE__ */ (0,
|
|
25184
|
-
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)(
|
|
25185
27461
|
AiSectionOverlay,
|
|
25186
27462
|
{
|
|
25187
27463
|
postToParent: postToParent2,
|
|
@@ -25189,7 +27465,7 @@ function OhhwellsBridge() {
|
|
|
25189
27465
|
onSelectionChange: handleAiSectionSelectionChange
|
|
25190
27466
|
}
|
|
25191
27467
|
),
|
|
25192
|
-
isEditMode && /* @__PURE__ */ (0,
|
|
27468
|
+
isEditMode && /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
|
|
25193
27469
|
AiMediaStripOverlay,
|
|
25194
27470
|
{
|
|
25195
27471
|
postToParent: postToParent2,
|
|
@@ -25198,7 +27474,7 @@ function OhhwellsBridge() {
|
|
|
25198
27474
|
clearInteractionChromeRef
|
|
25199
27475
|
}
|
|
25200
27476
|
),
|
|
25201
|
-
isEditMode && /* @__PURE__ */ (0,
|
|
27477
|
+
isEditMode && /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
|
|
25202
27478
|
AiPricingCardOverlay,
|
|
25203
27479
|
{
|
|
25204
27480
|
postToParent: postToParent2,
|
|
@@ -25206,12 +27482,12 @@ function OhhwellsBridge() {
|
|
|
25206
27482
|
applyTreeLocalRef
|
|
25207
27483
|
}
|
|
25208
27484
|
),
|
|
25209
|
-
isSectionDragging && sectionDropSlots.map((slot, i) => /* @__PURE__ */ (0,
|
|
27485
|
+
isSectionDragging && sectionDropSlots.map((slot, i) => /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
|
|
25210
27486
|
"div",
|
|
25211
27487
|
{
|
|
25212
27488
|
className: "pointer-events-none fixed z-2147483646",
|
|
25213
27489
|
style: { left: slot.left, top: slot.y, width: slot.width, height: 3, transform: "translateY(-50%)" },
|
|
25214
|
-
children: /* @__PURE__ */ (0,
|
|
27490
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
|
|
25215
27491
|
DropIndicator,
|
|
25216
27492
|
{
|
|
25217
27493
|
direction: "horizontal",
|
|
@@ -25222,7 +27498,7 @@ function OhhwellsBridge() {
|
|
|
25222
27498
|
},
|
|
25223
27499
|
`section-drop-${slot.insertIndex}-${i}`
|
|
25224
27500
|
)),
|
|
25225
|
-
Object.entries(uploadingRects).map(([key, { rect, fadingOut }]) => /* @__PURE__ */ (0,
|
|
27501
|
+
Object.entries(uploadingRects).map(([key, { rect, fadingOut }]) => /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
|
|
25226
27502
|
MediaOverlay,
|
|
25227
27503
|
{
|
|
25228
27504
|
hover: { key, rect, elementType: "image", isDragOver: false, hasTextOverlap: false },
|
|
@@ -25233,7 +27509,7 @@ function OhhwellsBridge() {
|
|
|
25233
27509
|
},
|
|
25234
27510
|
`uploading-${key}`
|
|
25235
27511
|
)),
|
|
25236
|
-
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)(
|
|
25237
27513
|
MediaOverlay,
|
|
25238
27514
|
{
|
|
25239
27515
|
hover: mediaHover,
|
|
@@ -25244,7 +27520,7 @@ function OhhwellsBridge() {
|
|
|
25244
27520
|
onVideoSettingsChange: handleVideoSettingsChange
|
|
25245
27521
|
}
|
|
25246
27522
|
),
|
|
25247
|
-
selectedMedia && !(selectedMedia.key in uploadingRects) && !linkPopover && /* @__PURE__ */ (0,
|
|
27523
|
+
selectedMedia && !(selectedMedia.key in uploadingRects) && !linkPopover && /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
|
|
25248
27524
|
MediaOverlay,
|
|
25249
27525
|
{
|
|
25250
27526
|
hover: selectedMedia,
|
|
@@ -25256,7 +27532,7 @@ function OhhwellsBridge() {
|
|
|
25256
27532
|
onVideoSettingsChange: handleVideoSettingsChange
|
|
25257
27533
|
}
|
|
25258
27534
|
),
|
|
25259
|
-
carouselHover && !linkPopover && !isItemDragging && /* @__PURE__ */ (0,
|
|
27535
|
+
carouselHover && !linkPopover && !isItemDragging && /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
|
|
25260
27536
|
CarouselOverlay,
|
|
25261
27537
|
{
|
|
25262
27538
|
hover: carouselHover,
|
|
@@ -25264,10 +27540,10 @@ function OhhwellsBridge() {
|
|
|
25264
27540
|
cueOnly: !!carouselHover.fullBleedSectionId && carouselHover.fullBleedSectionId !== selectedAiSectionId
|
|
25265
27541
|
}
|
|
25266
27542
|
),
|
|
25267
|
-
siblingHintRect && !linkPopover && !isItemDragging && siblingHintRects.length === 0 && /* @__PURE__ */ (0,
|
|
25268
|
-
siblingHintRects.length > 0 && !linkPopover && !isItemDragging && siblingHintRects.map((rect, i) => /* @__PURE__ */ (0,
|
|
25269
|
-
isItemDragging && draggedItemRect && selectedElRef.current !== footerDragRef.current?.draggedEl && selectedElRef.current !== navDragRef.current?.draggedEl && /* @__PURE__ */ (0,
|
|
25270
|
-
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)(
|
|
25271
27547
|
"div",
|
|
25272
27548
|
{
|
|
25273
27549
|
className: "pointer-events-none fixed z-2147483646",
|
|
@@ -25277,7 +27553,7 @@ function OhhwellsBridge() {
|
|
|
25277
27553
|
width: slot.width,
|
|
25278
27554
|
height: slot.height
|
|
25279
27555
|
},
|
|
25280
|
-
children: /* @__PURE__ */ (0,
|
|
27556
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
|
|
25281
27557
|
DropIndicator,
|
|
25282
27558
|
{
|
|
25283
27559
|
direction: slot.direction,
|
|
@@ -25288,7 +27564,7 @@ function OhhwellsBridge() {
|
|
|
25288
27564
|
},
|
|
25289
27565
|
`footer-drop-${slot.direction}-${slot.columnIndex}-${slot.insertIndex}-${i}`
|
|
25290
27566
|
)),
|
|
25291
|
-
isItemDragging && navDropSlots.map((slot, i) => /* @__PURE__ */ (0,
|
|
27567
|
+
isItemDragging && navDropSlots.map((slot, i) => /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
|
|
25292
27568
|
"div",
|
|
25293
27569
|
{
|
|
25294
27570
|
className: "pointer-events-none fixed z-2147483646",
|
|
@@ -25298,7 +27574,7 @@ function OhhwellsBridge() {
|
|
|
25298
27574
|
width: slot.width,
|
|
25299
27575
|
height: slot.height
|
|
25300
27576
|
},
|
|
25301
|
-
children: /* @__PURE__ */ (0,
|
|
27577
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
|
|
25302
27578
|
DropIndicator,
|
|
25303
27579
|
{
|
|
25304
27580
|
direction: slot.direction,
|
|
@@ -25309,10 +27585,31 @@ function OhhwellsBridge() {
|
|
|
25309
27585
|
},
|
|
25310
27586
|
`nav-drop-${slot.direction}-${slot.parentId ?? "root"}-${slot.insertIndex}-${i}`
|
|
25311
27587
|
)),
|
|
25312
|
-
|
|
25313
|
-
|
|
25314
|
-
|
|
25315
|
-
|
|
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)(
|
|
25316
27613
|
ItemInteractionLayer,
|
|
25317
27614
|
{
|
|
25318
27615
|
rect: formPickRect,
|
|
@@ -25320,13 +27617,13 @@ function OhhwellsBridge() {
|
|
|
25320
27617
|
itemDragSurface: false,
|
|
25321
27618
|
toolbarAlign: "left",
|
|
25322
27619
|
chromeGap: 24,
|
|
25323
|
-
toolbar: fieldPickRect ? void 0 : /* @__PURE__ */ (0,
|
|
27620
|
+
toolbar: fieldPickRect ? void 0 : /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)(
|
|
25324
27621
|
"div",
|
|
25325
27622
|
{
|
|
25326
27623
|
"data-ohw-form-toolbar": "",
|
|
25327
27624
|
className: "pointer-events-auto flex items-center gap-0.5 whitespace-nowrap rounded-lg border border-border bg-background p-1 shadow-md",
|
|
25328
27625
|
children: [
|
|
25329
|
-
/* @__PURE__ */ (0,
|
|
27626
|
+
/* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
|
|
25330
27627
|
"button",
|
|
25331
27628
|
{
|
|
25332
27629
|
type: "button",
|
|
@@ -25334,11 +27631,11 @@ function OhhwellsBridge() {
|
|
|
25334
27631
|
className: "flex h-7 w-7 items-center justify-center rounded-md text-foreground transition-colors hover:bg-muted/80",
|
|
25335
27632
|
onClick: () => setFieldTypePickerOpen((open) => !open),
|
|
25336
27633
|
"data-ohw-add-field": "",
|
|
25337
|
-
children: /* @__PURE__ */ (0,
|
|
27634
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(import_lucide_react20.Plus, { size: 15, "aria-hidden": true })
|
|
25338
27635
|
}
|
|
25339
27636
|
),
|
|
25340
|
-
/* @__PURE__ */ (0,
|
|
25341
|
-
/* @__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)(
|
|
25342
27639
|
"button",
|
|
25343
27640
|
{
|
|
25344
27641
|
type: "button",
|
|
@@ -25354,11 +27651,11 @@ function OhhwellsBridge() {
|
|
|
25354
27651
|
});
|
|
25355
27652
|
},
|
|
25356
27653
|
children: [
|
|
25357
|
-
/* @__PURE__ */ (0,
|
|
27654
|
+
/* @__PURE__ */ (0, import_jsx_runtime36.jsx)(import_lucide_react20.Settings, { size: 14, "aria-hidden": true }),
|
|
25358
27655
|
"Form settings",
|
|
25359
27656
|
formPickCount ? (
|
|
25360
27657
|
// Counter pill, per the design — not a text suffix.
|
|
25361
|
-
/* @__PURE__ */ (0,
|
|
27658
|
+
/* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
|
|
25362
27659
|
"span",
|
|
25363
27660
|
{
|
|
25364
27661
|
"data-ohw-form-count": "",
|
|
@@ -25370,8 +27667,8 @@ function OhhwellsBridge() {
|
|
|
25370
27667
|
]
|
|
25371
27668
|
}
|
|
25372
27669
|
),
|
|
25373
|
-
/* @__PURE__ */ (0,
|
|
25374
|
-
/* @__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)(
|
|
25375
27672
|
"button",
|
|
25376
27673
|
{
|
|
25377
27674
|
type: "button",
|
|
@@ -25402,7 +27699,7 @@ function OhhwellsBridge() {
|
|
|
25402
27699
|
)
|
|
25403
27700
|
}
|
|
25404
27701
|
),
|
|
25405
|
-
formHoverRect && !isItemDragging && /* @__PURE__ */ (0,
|
|
27702
|
+
formHoverRect && !isItemDragging && /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
|
|
25406
27703
|
ItemInteractionLayer,
|
|
25407
27704
|
{
|
|
25408
27705
|
rect: formHoverRect,
|
|
@@ -25410,7 +27707,7 @@ function OhhwellsBridge() {
|
|
|
25410
27707
|
chromeGap: formHoverElRef.current && getFieldWrapper(formHoverElRef.current) ? 8 : 24
|
|
25411
27708
|
}
|
|
25412
27709
|
),
|
|
25413
|
-
fieldPickRect && fieldPickState && !isItemDragging && toolbarVariant !== "rich-text" && /* @__PURE__ */ (0,
|
|
27710
|
+
fieldPickRect && fieldPickState && !isItemDragging && toolbarVariant !== "rich-text" && /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
|
|
25414
27711
|
ItemInteractionLayer,
|
|
25415
27712
|
{
|
|
25416
27713
|
rect: fieldPickRect,
|
|
@@ -25422,7 +27719,7 @@ function OhhwellsBridge() {
|
|
|
25422
27719
|
dragHandleLabel: "Reorder field",
|
|
25423
27720
|
onDragHandleDragStart: handleFieldDragStart,
|
|
25424
27721
|
onDragHandleDragEnd: handleFieldDragEnd,
|
|
25425
|
-
toolbar: /* @__PURE__ */ (0,
|
|
27722
|
+
toolbar: /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
|
|
25426
27723
|
FormFieldToolbar,
|
|
25427
27724
|
{
|
|
25428
27725
|
type: fieldPickState.type,
|
|
@@ -25435,12 +27732,12 @@ function OhhwellsBridge() {
|
|
|
25435
27732
|
)
|
|
25436
27733
|
}
|
|
25437
27734
|
),
|
|
25438
|
-
fieldDragging ? fieldDropSlots.map((slot, i) => /* @__PURE__ */ (0,
|
|
27735
|
+
fieldDragging ? fieldDropSlots.map((slot, i) => /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
|
|
25439
27736
|
"div",
|
|
25440
27737
|
{
|
|
25441
27738
|
className: "pointer-events-none fixed z-[2147483644]",
|
|
25442
27739
|
style: { top: slot.top, left: slot.left, width: slot.width },
|
|
25443
|
-
children: /* @__PURE__ */ (0,
|
|
27740
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
|
|
25444
27741
|
DropIndicator,
|
|
25445
27742
|
{
|
|
25446
27743
|
direction: "horizontal",
|
|
@@ -25453,7 +27750,7 @@ function OhhwellsBridge() {
|
|
|
25453
27750
|
)) : null,
|
|
25454
27751
|
fieldTypePickerOpen && formPickRect ? (() => {
|
|
25455
27752
|
const toolbar = document.querySelector("[data-ohw-form-toolbar]")?.getBoundingClientRect();
|
|
25456
|
-
return /* @__PURE__ */ (0,
|
|
27753
|
+
return /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
|
|
25457
27754
|
"div",
|
|
25458
27755
|
{
|
|
25459
27756
|
className: "pointer-events-none fixed z-[2147483645]",
|
|
@@ -25461,12 +27758,12 @@ function OhhwellsBridge() {
|
|
|
25461
27758
|
top: toolbar ? toolbar.bottom + 6 : formPickRect.top + 16,
|
|
25462
27759
|
left: toolbar ? toolbar.left : formPickRect.left + 24
|
|
25463
27760
|
},
|
|
25464
|
-
children: /* @__PURE__ */ (0,
|
|
27761
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(FieldTypePicker, { onPick: handleAddField })
|
|
25465
27762
|
}
|
|
25466
27763
|
);
|
|
25467
27764
|
})() : null,
|
|
25468
|
-
toolbarVariant === "select-frame" && toolbarRect && !linkPopover && !isItemDragging && !isFooterFrameSelection && selectedElRef.current && isNavbarLinksContainer2(selectedElRef.current) && /* @__PURE__ */ (0,
|
|
25469
|
-
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)(
|
|
25470
27767
|
FooterContainerChrome,
|
|
25471
27768
|
{
|
|
25472
27769
|
rect: toolbarRect,
|
|
@@ -25474,13 +27771,17 @@ function OhhwellsBridge() {
|
|
|
25474
27771
|
addDisabled: !canAddFooterColumn()
|
|
25475
27772
|
}
|
|
25476
27773
|
),
|
|
25477
|
-
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)(
|
|
25478
27775
|
ItemInteractionLayer,
|
|
25479
27776
|
{
|
|
25480
|
-
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,
|
|
25481
27778
|
toolbarBelowRect: selectedElRef.current && isNavigationItem2(selectedElRef.current) ? getOpenNavDropdownPanelRect(selectedElRef.current) : null,
|
|
25482
27779
|
toolbarBelowEl: selectedElRef.current && isNavigationItem2(selectedElRef.current) ? getOpenNavDropdownPanel(selectedElRef.current) : null,
|
|
25483
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
|
+
),
|
|
25484
27785
|
state: isItemDragging ? "dragging" : selectedElRef.current && isNavigationItem2(selectedElRef.current) && getOpenNavDropdownPanel(selectedElRef.current) ? "active-bottom" : resolveItemInteractionState(toolbarRect, parentScrollRef.current),
|
|
25485
27786
|
showHandle: toolbarVariant === "link-action" && Boolean(reorderHrefKey) || toolbarVariant === "select-frame" && isFooterFrameSelection,
|
|
25486
27787
|
dragDisabled: reorderDragDisabled,
|
|
@@ -25490,18 +27791,25 @@ function OhhwellsBridge() {
|
|
|
25490
27791
|
onItemPointerDown: toolbarVariant === "logo" ? void 0 : handleItemChromePointerDown,
|
|
25491
27792
|
onItemClick: toolbarVariant === "logo" ? void 0 : handleItemChromeClick,
|
|
25492
27793
|
itemDragSurface: toolbarVariant !== "logo" && !isFooterFrameSelection && !selectedIsSocialsRow,
|
|
25493
|
-
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)(
|
|
25494
27795
|
ItemActionToolbar,
|
|
25495
27796
|
{
|
|
25496
27797
|
onEditLink: openLinkPopoverForSelected,
|
|
25497
27798
|
onStyle: () => {
|
|
25498
27799
|
const row = selectedElRef.current;
|
|
25499
27800
|
if (!row) return;
|
|
25500
|
-
|
|
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();
|
|
25501
27809
|
else openSocialsDisplayPanel(row);
|
|
25502
27810
|
},
|
|
25503
|
-
showStyle: selectedIsSocialsRow,
|
|
25504
|
-
styleActive: floatingPanel?.kind === "socials-display",
|
|
27811
|
+
showStyle: selectedIsSocialsRow || selectedIsCta,
|
|
27812
|
+
styleActive: floatingPanel?.kind === "socials-display" || floatingPanel?.kind === "button-style",
|
|
25505
27813
|
onAddItem: handleAddChildItem,
|
|
25506
27814
|
onSelectParent: handleSelectParent,
|
|
25507
27815
|
onDuplicate: handleDuplicateSelected,
|
|
@@ -25512,11 +27820,11 @@ function OhhwellsBridge() {
|
|
|
25512
27820
|
})(),
|
|
25513
27821
|
editLinkDisabled: false,
|
|
25514
27822
|
moreDisabled: false,
|
|
25515
|
-
deleteDisabled: selectedElRef.current !== null && (() => {
|
|
27823
|
+
deleteDisabled: selectedElRef.current !== null && isCtaButton(selectedElRef.current) && !canDeleteButton(selectedElRef.current) || selectedElRef.current !== null && (() => {
|
|
25516
27824
|
const social = getSocialItem(selectedElRef.current);
|
|
25517
27825
|
return social ? !canRemoveSocialItem(social) : false;
|
|
25518
27826
|
})(),
|
|
25519
|
-
duplicateDisabled: isFooterFrameSelection || selectedIsSocialsRow || selectedElRef.current !== null && (() => {
|
|
27827
|
+
duplicateDisabled: isFooterFrameSelection || selectedIsSocialsRow || selectedElRef.current !== null && isCtaButton(selectedElRef.current) && !canDuplicateButton(selectedElRef.current) || selectedElRef.current !== null && (() => {
|
|
25520
27828
|
const social = getSocialItem(selectedElRef.current);
|
|
25521
27829
|
const row = social ? findSocialsRow(social) : null;
|
|
25522
27830
|
return row ? !canAddSocialItem(row) : false;
|
|
@@ -25525,7 +27833,7 @@ function OhhwellsBridge() {
|
|
|
25525
27833
|
showAddItem: isFooterFrameSelection || selectedIsSocialsRow || !selectedIsCta && Boolean(
|
|
25526
27834
|
selectedElRef.current && isNavbarHrefKey(selectedElRef.current.getAttribute("data-ohw-href-key")) && !isNestedNavChild(selectedElRef.current)
|
|
25527
27835
|
),
|
|
25528
|
-
showMore:
|
|
27836
|
+
showMore: !selectedIsSocialsRow,
|
|
25529
27837
|
dropdownOpen: navDropdownPreviewOpen,
|
|
25530
27838
|
onDropdownOpenChange: handleNavDropdownOpenChange,
|
|
25531
27839
|
headingVisible: footerHeadingVisible,
|
|
@@ -25534,8 +27842,8 @@ function OhhwellsBridge() {
|
|
|
25534
27842
|
) : void 0
|
|
25535
27843
|
}
|
|
25536
27844
|
),
|
|
25537
|
-
toolbarRect && toolbarVariant === "rich-text" && !linkPopover && !isRectOutsideClip(toolbarRect, getIframeVisibleClip(parentScrollRef.current)) && /* @__PURE__ */ (0,
|
|
25538
|
-
/* @__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)(
|
|
25539
27847
|
EditGlowChrome,
|
|
25540
27848
|
{
|
|
25541
27849
|
rect: toolbarRect,
|
|
@@ -25545,7 +27853,7 @@ function OhhwellsBridge() {
|
|
|
25545
27853
|
hideHandle: isItemDragging
|
|
25546
27854
|
}
|
|
25547
27855
|
),
|
|
25548
|
-
/* @__PURE__ */ (0,
|
|
27856
|
+
/* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
|
|
25549
27857
|
FloatingToolbar,
|
|
25550
27858
|
{
|
|
25551
27859
|
rect: toolbarRect,
|
|
@@ -25558,7 +27866,7 @@ function OhhwellsBridge() {
|
|
|
25558
27866
|
}
|
|
25559
27867
|
)
|
|
25560
27868
|
] }),
|
|
25561
|
-
maxBadge && /* @__PURE__ */ (0,
|
|
27869
|
+
maxBadge && /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)(
|
|
25562
27870
|
"div",
|
|
25563
27871
|
{
|
|
25564
27872
|
"data-ohw-max-badge": "",
|
|
@@ -25584,7 +27892,7 @@ function OhhwellsBridge() {
|
|
|
25584
27892
|
]
|
|
25585
27893
|
}
|
|
25586
27894
|
),
|
|
25587
|
-
toggleState && !linkPopover && /* @__PURE__ */ (0,
|
|
27895
|
+
toggleState && !linkPopover && /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
|
|
25588
27896
|
StateToggle,
|
|
25589
27897
|
{
|
|
25590
27898
|
rect: toggleState.rect,
|
|
@@ -25593,15 +27901,15 @@ function OhhwellsBridge() {
|
|
|
25593
27901
|
onStateChange: handleStateChange
|
|
25594
27902
|
}
|
|
25595
27903
|
),
|
|
25596
|
-
sectionGap && !linkPopover && /* @__PURE__ */ (0,
|
|
27904
|
+
sectionGap && !linkPopover && /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)(
|
|
25597
27905
|
"div",
|
|
25598
27906
|
{
|
|
25599
27907
|
"data-ohw-section-insert-line": "",
|
|
25600
27908
|
className: "fixed left-0 w-full z-2147483646 flex items-center pointer-events-none",
|
|
25601
27909
|
style: { top: sectionGap.y, transform: "translateY(-50%)" },
|
|
25602
27910
|
children: [
|
|
25603
|
-
/* @__PURE__ */ (0,
|
|
25604
|
-
/* @__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)(
|
|
25605
27913
|
Badge,
|
|
25606
27914
|
{
|
|
25607
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",
|
|
@@ -25618,11 +27926,11 @@ function OhhwellsBridge() {
|
|
|
25618
27926
|
children: "Add Section"
|
|
25619
27927
|
}
|
|
25620
27928
|
),
|
|
25621
|
-
/* @__PURE__ */ (0,
|
|
27929
|
+
/* @__PURE__ */ (0, import_jsx_runtime36.jsx)("div", { className: "flex-1 bg-bridge-primary", style: { height: 3 } })
|
|
25622
27930
|
]
|
|
25623
27931
|
}
|
|
25624
27932
|
),
|
|
25625
|
-
linkPopover && dialogPortalContainer ? /* @__PURE__ */ (0,
|
|
27933
|
+
linkPopover && dialogPortalContainer ? /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
|
|
25626
27934
|
LinkPopover,
|
|
25627
27935
|
{
|
|
25628
27936
|
panelRef: linkPopoverPanelRef,
|
|
@@ -25639,7 +27947,7 @@ function OhhwellsBridge() {
|
|
|
25639
27947
|
},
|
|
25640
27948
|
linkPopover.key
|
|
25641
27949
|
) : null,
|
|
25642
|
-
floatingPanel && floatingPanel.kind === "socials-display" ? /* @__PURE__ */ (0,
|
|
27950
|
+
floatingPanel && floatingPanel.kind === "socials-display" ? /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
|
|
25643
27951
|
FloatingPanel,
|
|
25644
27952
|
{
|
|
25645
27953
|
open: true,
|
|
@@ -25649,7 +27957,7 @@ function OhhwellsBridge() {
|
|
|
25649
27957
|
onPositionChange: setFloatingPanelPos,
|
|
25650
27958
|
parentScroll: parentScrollSnap ?? parentScrollRef.current,
|
|
25651
27959
|
onClose: closeFloatingPanelOnly,
|
|
25652
|
-
children: /* @__PURE__ */ (0,
|
|
27960
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
|
|
25653
27961
|
SocialsDisplayPanel,
|
|
25654
27962
|
{
|
|
25655
27963
|
display: socialsDisplayFor(floatingPanel.row, editContentRef.current),
|
|
@@ -25660,12 +27968,106 @@ function OhhwellsBridge() {
|
|
|
25660
27968
|
}
|
|
25661
27969
|
)
|
|
25662
27970
|
}
|
|
25663
|
-
) : 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
|
|
25664
28013
|
] }),
|
|
25665
28014
|
bridgeRoot
|
|
25666
28015
|
) : null
|
|
25667
28016
|
] });
|
|
25668
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
|
+
}
|
|
25669
28071
|
// Annotate the CommonJS export names for ESM import in node:
|
|
25670
28072
|
0 && (module.exports = {
|
|
25671
28073
|
AI_DEFAULT_BRAND,
|
|
@@ -25683,6 +28085,7 @@ function OhhwellsBridge() {
|
|
|
25683
28085
|
DropdownMenuItem,
|
|
25684
28086
|
DropdownMenuSeparator,
|
|
25685
28087
|
DropdownMenuTrigger,
|
|
28088
|
+
EmptySection,
|
|
25686
28089
|
ItemActionToolbar,
|
|
25687
28090
|
ItemInteractionLayer,
|
|
25688
28091
|
LinkEditorPanel,
|