@ohhwells/bridge 0.1.113-next.301 → 0.1.113-next.303

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 CHANGED
@@ -633,9 +633,9 @@ function styleSheetCss() {
633
633
  );
634
634
  }
635
635
  const pad = { tight: 40, balanced: 64, airy: 96 };
636
- for (const [spacing, px] of Object.entries(pad)) {
636
+ for (const [spacing, px2] of Object.entries(pad)) {
637
637
  rules.push(
638
- `[data-ohw-style-spacing="${spacing}"] { padding-top: ${px}px !important; padding-bottom: ${px}px !important; }`
638
+ `[data-ohw-style-spacing="${spacing}"] { padding-top: ${px2}px !important; padding-bottom: ${px2}px !important; }`
639
639
  );
640
640
  }
641
641
  rules.push(
@@ -3046,12 +3046,12 @@ function deriveTemplateButtonStyle() {
3046
3046
  cs.borderBottomLeftRadius
3047
3047
  ].map((v) => v || "0px");
3048
3048
  const radius = corners.every((v) => v === corners[0]) ? corners[0] : corners.join(" ");
3049
- const px = (v) => parseFloat(v) || 0;
3050
- const lineHeight = px(cs.lineHeight) || px(cs.fontSize) * 1.2;
3051
- const contentH = btn.getBoundingClientRect().height - px(cs.borderTopWidth) - px(cs.borderBottomWidth);
3049
+ const px2 = (v) => parseFloat(v) || 0;
3050
+ const lineHeight = px2(cs.lineHeight) || px2(cs.fontSize) * 1.2;
3051
+ const contentH = btn.getBoundingClientRect().height - px2(cs.borderTopWidth) - px2(cs.borderBottomWidth);
3052
3052
  const impliedY = Math.round(Math.max(0, (contentH - lineHeight) / 2));
3053
- const padY = Math.max(px(cs.paddingTop), px(cs.paddingBottom), impliedY);
3054
- const padX = Math.max(px(cs.paddingLeft), px(cs.paddingRight));
3053
+ const padY = Math.max(px2(cs.paddingTop), px2(cs.paddingBottom), impliedY);
3054
+ const padX = Math.max(px2(cs.paddingLeft), px2(cs.paddingRight));
3055
3055
  return {
3056
3056
  radius: radius || "10px",
3057
3057
  padding: `${padY}px ${padX}px`,
@@ -7948,6 +7948,14 @@ function ItemActionToolbar({
7948
7948
  e.preventDefault();
7949
7949
  e.stopPropagation();
7950
7950
  onStyle?.();
7951
+ },
7952
+ // Same as Edit link: mousedown opens the panel and remounts this toolbar
7953
+ // (styleActive flips). Without stopping click, the gesture lands on whatever
7954
+ // is now under the cursor — navbar CTAs park the toolbar below the button, so
7955
+ // that miss deselects and the panel closes as soon as it opens.
7956
+ onClick: (e) => {
7957
+ e.preventDefault();
7958
+ e.stopPropagation();
7951
7959
  }
7952
7960
  },
7953
7961
  children: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(import_lucide_react3.Brush, { className: "size-4 shrink-0", "aria-hidden": true })
@@ -14651,6 +14659,1174 @@ function SocialsDisplayPanel({ display, onChange, className }) {
14651
14659
  ] });
14652
14660
  }
14653
14661
 
14662
+ // src/ui/button-style-panel.tsx
14663
+ var import_lucide_react15 = require("lucide-react");
14664
+
14665
+ // src/lib/button-styles.ts
14666
+ var BUTTON_VARIANTS_KEY = "__ohw_button_variants";
14667
+ var BUTTON_SIZES_KEY = "__ohw_button_sizes";
14668
+ var BUTTON_ASSIGNMENTS_KEY = "__ohw_button_assignments";
14669
+ var BUTTON_VARIANT_IDS = ["primary", "secondary", "ghost"];
14670
+ var BUTTON_SIZE_IDS = ["s", "m", "l"];
14671
+ var TRANSPARENT = "rgba(0, 0, 0, 0)";
14672
+ var REFERENCE_SIZES = {
14673
+ s: { height: 40, paddingTop: 8, paddingRight: 16, paddingBottom: 8, paddingLeft: 16, fontSize: 15, borderRadius: 8, gap: 8 },
14674
+ m: { height: 48, paddingTop: 12, paddingRight: 24, paddingBottom: 12, paddingLeft: 24, fontSize: 15, borderRadius: 8, gap: 8 },
14675
+ l: { height: 56, paddingTop: 16, paddingRight: 32, paddingBottom: 16, paddingLeft: 32, fontSize: 15, borderRadius: 8, gap: 8 }
14676
+ };
14677
+ function buttonStyleContext(_el) {
14678
+ return "Button";
14679
+ }
14680
+ function previewSlotBackground(el) {
14681
+ let node = el.parentElement;
14682
+ while (node && node !== el.ownerDocument.documentElement) {
14683
+ if (node.closest("[data-ohw-bridge], [data-ohw-bridge-root]")) {
14684
+ node = node.parentElement;
14685
+ continue;
14686
+ }
14687
+ const bg = getComputedStyle(node).backgroundColor;
14688
+ const parsed = parseColor(bg);
14689
+ if (parsed && !isTransparent(parsed)) return bg;
14690
+ node = node.parentElement;
14691
+ }
14692
+ const root = el.ownerDocument.documentElement;
14693
+ const style = getComputedStyle(root);
14694
+ for (const name of ["--brand-surface", "--brand-background", "--ohw-brand-light", "--color-light"]) {
14695
+ const value = style.getPropertyValue(name).trim();
14696
+ if (value) return value;
14697
+ }
14698
+ return "var(--brand-background, var(--ohw-brand-light, var(--color-light, #ffffff)))";
14699
+ }
14700
+ function buttonId(el) {
14701
+ if (!el) return null;
14702
+ const button = el.matches(CTA_BUTTON_SELECTOR) ? el : el.closest(CTA_BUTTON_SELECTOR);
14703
+ const id = button?.getAttribute("data-ohw-href-key")?.trim();
14704
+ return id || null;
14705
+ }
14706
+ function isButtonVariantId(value) {
14707
+ return BUTTON_VARIANT_IDS.includes(value);
14708
+ }
14709
+ function isButtonSizeId(value) {
14710
+ return BUTTON_SIZE_IDS.includes(value);
14711
+ }
14712
+ function px(value) {
14713
+ const rounded = Math.round(value * 100) / 100;
14714
+ return `${rounded}px`;
14715
+ }
14716
+ function parsePx(value, rootFont = 16) {
14717
+ if (!value) return 0;
14718
+ const n = parseFloat(value);
14719
+ if (!Number.isFinite(n)) return 0;
14720
+ if (value.trim().endsWith("rem") || value.trim().endsWith("em")) return n * rootFont;
14721
+ return n;
14722
+ }
14723
+ function classifyHeight(height) {
14724
+ if (height < 44) return "s";
14725
+ if (height < 52) return "m";
14726
+ return "l";
14727
+ }
14728
+ function scaleGeometry(geometry, scale = 0.75) {
14729
+ return {
14730
+ paddingTop: px(parsePx(geometry.paddingTop) * scale),
14731
+ paddingRight: px(parsePx(geometry.paddingRight) * scale),
14732
+ paddingBottom: px(parsePx(geometry.paddingBottom) * scale),
14733
+ paddingLeft: px(parsePx(geometry.paddingLeft) * scale),
14734
+ fontSize: px(parsePx(geometry.fontSize) * scale),
14735
+ borderRadius: px(parsePx(geometry.borderRadius) * scale),
14736
+ gap: px(parsePx(geometry.gap) * scale),
14737
+ height: Math.round(geometry.height * scale)
14738
+ };
14739
+ }
14740
+ function relativeLuminance(color) {
14741
+ const channel = (value) => {
14742
+ const s = value / 255;
14743
+ return s <= 0.03928 ? s / 12.92 : ((s + 0.055) / 1.055) ** 2.4;
14744
+ };
14745
+ return 0.2126 * channel(color.r) + 0.7152 * channel(color.g) + 0.0722 * channel(color.b);
14746
+ }
14747
+ function parseColor(input) {
14748
+ if (!input) return null;
14749
+ const value = input.trim().toLowerCase();
14750
+ if (value === "transparent") return { r: 0, g: 0, b: 0, a: 0 };
14751
+ const hex = value.match(/^#([0-9a-f]{3,8})$/);
14752
+ if (hex) {
14753
+ const raw = hex[1];
14754
+ const expand = (pair) => parseInt(pair.length === 1 ? pair + pair : pair, 16);
14755
+ if (raw.length === 3 || raw.length === 4) {
14756
+ return {
14757
+ r: expand(raw[0]),
14758
+ g: expand(raw[1]),
14759
+ b: expand(raw[2]),
14760
+ a: raw.length === 4 ? expand(raw[3]) / 255 : 1
14761
+ };
14762
+ }
14763
+ if (raw.length === 6 || raw.length === 8) {
14764
+ return {
14765
+ r: expand(raw.slice(0, 2)),
14766
+ g: expand(raw.slice(2, 4)),
14767
+ b: expand(raw.slice(4, 6)),
14768
+ a: raw.length === 8 ? expand(raw.slice(6, 8)) / 255 : 1
14769
+ };
14770
+ }
14771
+ }
14772
+ const rgb = value.match(
14773
+ /^rgba?\(\s*([\d.]+)[%\s,]+([\d.]+)[%\s,]+([\d.]+)(?:%?\s*[,/]\s*([\d.]+%?))?\s*\)$/
14774
+ );
14775
+ if (rgb) {
14776
+ const alphaRaw = rgb[4];
14777
+ const alpha = alphaRaw == null ? 1 : alphaRaw.endsWith("%") ? parseFloat(alphaRaw) / 100 : parseFloat(alphaRaw);
14778
+ return { r: Number(rgb[1]), g: Number(rgb[2]), b: Number(rgb[3]), a: alpha };
14779
+ }
14780
+ const oklch = value.match(
14781
+ /^oklch\(\s*([\d.]+%?)\s+([\d.]+)\s+([\d.]+)(?:deg)?(?:\s*\/\s*([\d.]+%?))?\s*\)$/
14782
+ );
14783
+ if (oklch) {
14784
+ const Lraw = oklch[1];
14785
+ const L = Lraw.endsWith("%") ? parseFloat(Lraw) / 100 : parseFloat(Lraw);
14786
+ const gray = Math.max(0, Math.min(1, L)) * 255;
14787
+ const alphaRaw = oklch[4];
14788
+ const alpha = alphaRaw == null ? 1 : alphaRaw.endsWith("%") ? parseFloat(alphaRaw) / 100 : parseFloat(alphaRaw);
14789
+ return { r: gray, g: gray, b: gray, a: alpha };
14790
+ }
14791
+ return null;
14792
+ }
14793
+ function isTransparent(color) {
14794
+ return !color || color.a < 0.05;
14795
+ }
14796
+ function hasOpaqueBackground(background) {
14797
+ if (!background) return false;
14798
+ const value = background.trim().toLowerCase();
14799
+ if (!value || value === "transparent" || value === "rgba(0, 0, 0, 0)" || value === "rgb(0, 0, 0, 0)") {
14800
+ return false;
14801
+ }
14802
+ const parsed = parseColor(background);
14803
+ if (parsed) return !isTransparent(parsed);
14804
+ return true;
14805
+ }
14806
+ function toCss(color) {
14807
+ const r2 = Math.round(color.r);
14808
+ const g = Math.round(color.g);
14809
+ const b = Math.round(color.b);
14810
+ if (color.a >= 0.995) return `rgb(${r2}, ${g}, ${b})`;
14811
+ return `rgba(${r2}, ${g}, ${b}, ${Math.round(color.a * 100) / 100})`;
14812
+ }
14813
+ function colorKey(input) {
14814
+ const parsed = parseColor(input);
14815
+ if (!parsed || isTransparent(parsed)) return "transparent";
14816
+ return `${Math.round(parsed.r / 8)}-${Math.round(parsed.g / 8)}-${Math.round(parsed.b / 8)}-${Math.round(parsed.a * 4)}`;
14817
+ }
14818
+ function declaredVariant(className) {
14819
+ const match = className.match(/\bbtn--(primary|secondary|ghost)\b/);
14820
+ return match && isButtonVariantId(match[1]) ? match[1] : null;
14821
+ }
14822
+ function fillSlot(sample) {
14823
+ if (hasOpaqueBackground(sample.background)) return "primary";
14824
+ const width = parseFloat(sample.borderWidth);
14825
+ const border = parseColor(sample.borderColor);
14826
+ if (width > 0 && !isTransparent(border)) return "secondary";
14827
+ return "ghost";
14828
+ }
14829
+ function sampleSlot(sample) {
14830
+ return declaredVariant(sample.className) ?? fillSlot(sample);
14831
+ }
14832
+ function fingerprint(sample) {
14833
+ const width = parseFloat(sample.borderWidth);
14834
+ const border = width > 0 ? colorKey(sample.borderColor) : "none";
14835
+ return `${colorKey(sample.background)}|${border}|${colorKey(sample.color)}|${sampleSlot(sample)}`;
14836
+ }
14837
+ function paintColor(chrome) {
14838
+ if (hasOpaqueBackground(chrome.background)) {
14839
+ const parsed = parseColor(chrome.background);
14840
+ return parsed ? toCss({ ...parsed, a: 1 }) : chrome.background;
14841
+ }
14842
+ const width = parseFloat(chrome.borderWidth);
14843
+ if (width > 0 && hasOpaqueBackground(chrome.borderColor)) {
14844
+ const parsed = parseColor(chrome.borderColor);
14845
+ return parsed ? toCss({ ...parsed, a: 1 }) : chrome.borderColor;
14846
+ }
14847
+ const text = parseColor(chrome.color);
14848
+ return text ? toCss({ ...text, a: 1 }) : chrome.color;
14849
+ }
14850
+ function chromeFrom(sample) {
14851
+ return {
14852
+ background: sample.background || TRANSPARENT,
14853
+ color: sample.color || "currentColor",
14854
+ borderColor: sample.borderColor || TRANSPARENT,
14855
+ borderWidth: sample.borderWidth || "0px"
14856
+ };
14857
+ }
14858
+ function filledPrimary(seed) {
14859
+ const paint = parseColor(paintColor(seed)) ?? { r: 15, g: 15, b: 15, a: 1 };
14860
+ const luminance = relativeLuminance(paint);
14861
+ return {
14862
+ background: toCss({ ...paint, a: 1 }),
14863
+ color: luminance > 0.55 ? "rgb(15, 15, 15)" : "rgb(255, 255, 255)",
14864
+ borderColor: TRANSPARENT,
14865
+ borderWidth: "0px"
14866
+ };
14867
+ }
14868
+ function generatedSecondary(primary) {
14869
+ const paint = paintColor(primary);
14870
+ return {
14871
+ background: TRANSPARENT,
14872
+ color: paint,
14873
+ borderColor: paint,
14874
+ borderWidth: "1px"
14875
+ };
14876
+ }
14877
+ function generatedGhost(primary) {
14878
+ return {
14879
+ background: TRANSPARENT,
14880
+ color: paintColor(primary),
14881
+ borderColor: TRANSPARENT,
14882
+ borderWidth: "0px"
14883
+ };
14884
+ }
14885
+ function normalizeOutlineChrome(outline, primary) {
14886
+ const paint = paintColor(primary);
14887
+ const text = parseColor(outline.color);
14888
+ const paintRgb = parseColor(paint);
14889
+ const primaryLabel = parseColor(primary.color);
14890
+ const matchesOnPrimary = Boolean(text && primaryLabel) && colorKey(outline.color) === colorKey(primary.color);
14891
+ const textTooLight = text ? relativeLuminance(text) > 0.7 : false;
14892
+ const paintIsDarker = paintRgb ? relativeLuminance(paintRgb) < 0.65 : hasOpaqueBackground(primary.background);
14893
+ if (!(matchesOnPrimary || textTooLight) || !paintIsDarker) return outline;
14894
+ const hasBorder = parseFloat(outline.borderWidth) > 0;
14895
+ return {
14896
+ ...outline,
14897
+ color: paint,
14898
+ borderColor: hasBorder ? paint : outline.borderColor
14899
+ };
14900
+ }
14901
+ function generateButtonVariants(samples) {
14902
+ if (samples.length === 0) return { status: "unresolved" };
14903
+ const groups = /* @__PURE__ */ new Map();
14904
+ for (const sample of samples) {
14905
+ const key = fingerprint(sample);
14906
+ const list = groups.get(key) ?? [];
14907
+ list.push(sample);
14908
+ groups.set(key, list);
14909
+ }
14910
+ if (groups.size > 3) return { status: "unresolved" };
14911
+ const bySlot = /* @__PURE__ */ new Map();
14912
+ for (const group of groups.values()) {
14913
+ const sample = group[0];
14914
+ const slot = sampleSlot(sample);
14915
+ if (bySlot.has(slot)) return { status: "unresolved" };
14916
+ bySlot.set(slot, sample);
14917
+ }
14918
+ const primarySample = bySlot.get("primary");
14919
+ const seed = chromeFrom(primarySample ?? samples[0]);
14920
+ const primary = primarySample ? seed : filledPrimary(seed);
14921
+ const secondary = normalizeOutlineChrome(
14922
+ bySlot.has("secondary") ? chromeFrom(bySlot.get("secondary")) : generatedSecondary(primary),
14923
+ primary
14924
+ );
14925
+ const ghost = normalizeOutlineChrome(
14926
+ bySlot.has("ghost") ? chromeFrom(bySlot.get("ghost")) : generatedGhost(primary),
14927
+ primary
14928
+ );
14929
+ return {
14930
+ status: "ready",
14931
+ tokens: { primary, secondary, ghost }
14932
+ };
14933
+ }
14934
+ function geometryFromSample(sample) {
14935
+ return {
14936
+ paddingTop: px(sample.paddingTop),
14937
+ paddingRight: px(sample.paddingRight),
14938
+ paddingBottom: px(sample.paddingBottom),
14939
+ paddingLeft: px(sample.paddingLeft),
14940
+ fontSize: px(sample.fontSize),
14941
+ borderRadius: px(sample.borderRadius),
14942
+ gap: px(sample.gap),
14943
+ height: Math.round(sample.height)
14944
+ };
14945
+ }
14946
+ function shiftSample(base, steps) {
14947
+ return {
14948
+ height: Math.max(24, base.height + steps * 8),
14949
+ paddingTop: Math.max(0, base.paddingTop + steps * 4),
14950
+ paddingBottom: Math.max(0, base.paddingBottom + steps * 4),
14951
+ paddingLeft: Math.max(0, base.paddingLeft + steps * 8),
14952
+ paddingRight: Math.max(0, base.paddingRight + steps * 8),
14953
+ fontSize: base.fontSize,
14954
+ borderRadius: base.borderRadius,
14955
+ gap: base.gap
14956
+ };
14957
+ }
14958
+ function clusterSizes(samples) {
14959
+ const sorted = [...samples].sort((a, b) => a.height - b.height);
14960
+ const clusters = [];
14961
+ for (const sample of sorted) {
14962
+ const current = clusters[clusters.length - 1];
14963
+ const head = current?.[0];
14964
+ if (!current || !head || Math.abs(sample.height - head.height) > 2) clusters.push([sample]);
14965
+ else current.push(sample);
14966
+ }
14967
+ return clusters.map((group) => {
14968
+ const pick = (key) => group.reduce((sum, item) => sum + item[key], 0) / group.length;
14969
+ return {
14970
+ height: pick("height"),
14971
+ paddingTop: pick("paddingTop"),
14972
+ paddingRight: pick("paddingRight"),
14973
+ paddingBottom: pick("paddingBottom"),
14974
+ paddingLeft: pick("paddingLeft"),
14975
+ fontSize: pick("fontSize"),
14976
+ borderRadius: pick("borderRadius"),
14977
+ gap: pick("gap")
14978
+ };
14979
+ });
14980
+ }
14981
+ function tokensFromSamples(bySlot, radius, gap) {
14982
+ const fill = (id) => {
14983
+ const sample = bySlot[id] ?? REFERENCE_SIZES[id];
14984
+ return geometryFromSample({ ...sample, borderRadius: radius, gap });
14985
+ };
14986
+ return { s: fill("s"), m: fill("m"), l: fill("l") };
14987
+ }
14988
+ function interpolateSizes(known) {
14989
+ const order = BUTTON_SIZE_IDS;
14990
+ const indexOf = (id) => order.indexOf(id);
14991
+ const sorted = [...known].sort((a, b) => indexOf(a.id) - indexOf(b.id));
14992
+ const left = sorted[0];
14993
+ const right = sorted[1];
14994
+ const span = indexOf(right.id) - indexOf(left.id);
14995
+ const step = (key) => (right.sample[key] - left.sample[key]) / span;
14996
+ const at = (index) => {
14997
+ const steps = index - indexOf(left.id);
14998
+ return {
14999
+ height: left.sample.height + step("height") * steps,
15000
+ paddingTop: Math.max(0, left.sample.paddingTop + step("paddingTop") * steps),
15001
+ paddingBottom: Math.max(0, left.sample.paddingBottom + step("paddingBottom") * steps),
15002
+ paddingLeft: Math.max(0, left.sample.paddingLeft + step("paddingLeft") * steps),
15003
+ paddingRight: Math.max(0, left.sample.paddingRight + step("paddingRight") * steps),
15004
+ fontSize: Math.max(10, left.sample.fontSize + step("fontSize") * steps),
15005
+ borderRadius: left.sample.borderRadius,
15006
+ gap: left.sample.gap
15007
+ };
15008
+ };
15009
+ const bySlot = {
15010
+ [left.id]: left.sample,
15011
+ [right.id]: { ...right.sample, borderRadius: left.sample.borderRadius, gap: left.sample.gap }
15012
+ };
15013
+ for (const id of order) {
15014
+ if (!bySlot[id]) bySlot[id] = at(indexOf(id));
15015
+ }
15016
+ return tokensFromSamples(bySlot, left.sample.borderRadius, left.sample.gap);
15017
+ }
15018
+ function generateButtonSizes(samples) {
15019
+ const clusters = clusterSizes(samples.filter((sample) => sample.height > 0));
15020
+ if (clusters.length === 0) {
15021
+ return { status: "ready", tokens: tokensFromSamples(REFERENCE_SIZES, 8, 8) };
15022
+ }
15023
+ if (clusters.length > 3) return { status: "unresolved" };
15024
+ if (clusters.length === 3) {
15025
+ const sorted = [...clusters].sort((a, b) => a.height - b.height);
15026
+ const radius = sorted[1].borderRadius;
15027
+ const gap = sorted[1].gap;
15028
+ return {
15029
+ status: "ready",
15030
+ tokens: {
15031
+ s: geometryFromSample({ ...sorted[0], borderRadius: radius, gap }),
15032
+ m: geometryFromSample({ ...sorted[1], borderRadius: radius, gap }),
15033
+ l: geometryFromSample({ ...sorted[2], borderRadius: radius, gap })
15034
+ }
15035
+ };
15036
+ }
15037
+ if (clusters.length === 1) {
15038
+ const known = clusters[0];
15039
+ const slot = classifyHeight(known.height);
15040
+ const offset = BUTTON_SIZE_IDS.indexOf(slot);
15041
+ const bySlot = Object.fromEntries(
15042
+ BUTTON_SIZE_IDS.map((id, index) => [id, shiftSample(known, index - offset)])
15043
+ );
15044
+ bySlot[slot] = known;
15045
+ return { status: "ready", tokens: tokensFromSamples(bySlot, known.borderRadius, known.gap) };
15046
+ }
15047
+ const mapped = clusters.map((sample) => ({ id: classifyHeight(sample.height), sample }));
15048
+ if (mapped[0].id === mapped[1].id) {
15049
+ const larger = clusters.slice().sort((a, b) => b.height - a.height)[0];
15050
+ return generateButtonSizes([larger]);
15051
+ }
15052
+ return { status: "ready", tokens: interpolateSizes(mapped) };
15053
+ }
15054
+ function parseJson(raw) {
15055
+ if (!raw) return null;
15056
+ try {
15057
+ return JSON.parse(raw);
15058
+ } catch {
15059
+ return null;
15060
+ }
15061
+ }
15062
+ function isChrome(value) {
15063
+ if (!value || typeof value !== "object") return false;
15064
+ const chrome = value;
15065
+ return typeof chrome.background === "string" && typeof chrome.color === "string";
15066
+ }
15067
+ function isGeometry(value) {
15068
+ if (!value || typeof value !== "object") return false;
15069
+ const geometry = value;
15070
+ return typeof geometry.paddingTop === "string" && typeof geometry.height === "number";
15071
+ }
15072
+ function readVariantTokens(content) {
15073
+ const parsed = parseJson(content[BUTTON_VARIANTS_KEY]);
15074
+ if (!parsed) return null;
15075
+ if (!BUTTON_VARIANT_IDS.every((id) => isChrome(parsed[id]))) return null;
15076
+ return parsed;
15077
+ }
15078
+ function readSizeTokens(content) {
15079
+ const parsed = parseJson(content[BUTTON_SIZES_KEY]);
15080
+ if (!parsed) return null;
15081
+ if (!BUTTON_SIZE_IDS.every((id) => isGeometry(parsed[id]))) return null;
15082
+ return parsed;
15083
+ }
15084
+ function readAssignments(content) {
15085
+ const parsed = parseJson(content[BUTTON_ASSIGNMENTS_KEY]);
15086
+ if (!parsed || typeof parsed !== "object") return {};
15087
+ const next = {};
15088
+ for (const [id, value] of Object.entries(parsed)) {
15089
+ if (!value || !isButtonVariantId(value.variant) || !isButtonSizeId(value.size)) continue;
15090
+ next[id] = { variant: value.variant, size: value.size };
15091
+ }
15092
+ return next;
15093
+ }
15094
+ function cssLength(style, prop) {
15095
+ return style.getPropertyValue(prop) || "0px";
15096
+ }
15097
+ function readVariantSample(el) {
15098
+ const style = getComputedStyle(el);
15099
+ return {
15100
+ background: style.backgroundColor,
15101
+ color: style.color,
15102
+ borderColor: style.borderTopColor,
15103
+ borderWidth: style.borderTopWidth,
15104
+ className: el.className || ""
15105
+ };
15106
+ }
15107
+ function readSizeSample(el) {
15108
+ const style = getComputedStyle(el);
15109
+ const rootFont = parsePx(getComputedStyle(el.ownerDocument.documentElement).fontSize) || 16;
15110
+ const rect = el.getBoundingClientRect();
15111
+ return {
15112
+ height: rect.height,
15113
+ paddingTop: parsePx(cssLength(style, "padding-top"), rootFont),
15114
+ paddingRight: parsePx(cssLength(style, "padding-right"), rootFont),
15115
+ paddingBottom: parsePx(cssLength(style, "padding-bottom"), rootFont),
15116
+ paddingLeft: parsePx(cssLength(style, "padding-left"), rootFont),
15117
+ fontSize: parsePx(style.fontSize, rootFont),
15118
+ borderRadius: parsePx(style.borderTopLeftRadius, rootFont),
15119
+ gap: parsePx(style.columnGap || style.gap, rootFont)
15120
+ };
15121
+ }
15122
+ var buttonOriginByEl = /* @__PURE__ */ new WeakMap();
15123
+ function hasEditorPaint(el) {
15124
+ return el.hasAttribute("data-ohw-btn-variant") || el.hasAttribute("data-ohw-btn-size") || Boolean(el.style.background || el.style.padding || el.style.height);
15125
+ }
15126
+ function measureSourceOrigin(el) {
15127
+ const parent = el.parentElement;
15128
+ if (!parent) {
15129
+ return { variant: readVariantSample(el), size: readSizeSample(el) };
15130
+ }
15131
+ const probe = el.cloneNode(true);
15132
+ probe.removeAttribute("style");
15133
+ probe.removeAttribute("data-ohw-btn-variant");
15134
+ probe.removeAttribute("data-ohw-btn-size");
15135
+ probe.removeAttribute("data-ohw-selected");
15136
+ probe.setAttribute("data-ohw-btn-probe", "");
15137
+ for (const node of probe.querySelectorAll("[style]")) {
15138
+ node.removeAttribute("style");
15139
+ }
15140
+ probe.style.cssText = "position:absolute;left:-99999px;top:0;visibility:hidden;pointer-events:none;display:inline-flex;";
15141
+ parent.insertBefore(probe, el);
15142
+ void probe.offsetHeight;
15143
+ const origin = { variant: readVariantSample(probe), size: readSizeSample(probe) };
15144
+ probe.remove();
15145
+ return origin;
15146
+ }
15147
+ function captureButtonOrigin(el) {
15148
+ const cached = buttonOriginByEl.get(el);
15149
+ if (cached) return cached;
15150
+ const origin = hasEditorPaint(el) ? measureSourceOrigin(el) : { variant: readVariantSample(el), size: readSizeSample(el) };
15151
+ buttonOriginByEl.set(el, origin);
15152
+ return origin;
15153
+ }
15154
+ function listStyleButtons(doc) {
15155
+ return Array.from(doc.querySelectorAll(CTA_BUTTON_SELECTOR)).filter((el) => {
15156
+ if (el.closest("[data-ohw-bridge], [data-ohw-bridge-root]")) return false;
15157
+ const rect = el.getBoundingClientRect();
15158
+ return rect.width > 0 && rect.height > 0;
15159
+ });
15160
+ }
15161
+ function generateTokensFromButtons(buttons) {
15162
+ const variants = generateButtonVariants(buttons.map(readVariantSample));
15163
+ const sizes = generateButtonSizes(buttons.map(readSizeSample));
15164
+ if (variants.status !== "ready" || sizes.status !== "ready") return { status: "unresolved" };
15165
+ return { status: "ready", tokens: { variants: variants.tokens, sizes: sizes.tokens } };
15166
+ }
15167
+ function tokensFromButton(el) {
15168
+ const origin = captureButtonOrigin(el);
15169
+ const sample = origin.variant;
15170
+ const variants = generateButtonVariants([sample]);
15171
+ const sizes = generateButtonSizes([origin.size]);
15172
+ const primary = chromeFrom(sample);
15173
+ return {
15174
+ variants: variants.status === "ready" ? variants.tokens : { primary, secondary: generatedSecondary(primary), ghost: generatedGhost(primary) },
15175
+ sizes: sizes.status === "ready" ? sizes.tokens : tokensFromSamples(REFERENCE_SIZES, 8, 8)
15176
+ };
15177
+ }
15178
+ function readStoredStyleTokens(content) {
15179
+ const variants = readVariantTokens(content);
15180
+ const sizes = readSizeTokens(content);
15181
+ if (!variants || !sizes) return null;
15182
+ return { variants, sizes };
15183
+ }
15184
+ function styleTokenNodes(tokens) {
15185
+ return [
15186
+ { key: BUTTON_VARIANTS_KEY, text: JSON.stringify(tokens.variants) },
15187
+ { key: BUTTON_SIZES_KEY, text: JSON.stringify(tokens.sizes) }
15188
+ ];
15189
+ }
15190
+ function ensureButtonStyleTokens(doc, content) {
15191
+ const stored = readStoredStyleTokens(content);
15192
+ if (stored) return { tokens: stored, nodes: [] };
15193
+ const generated = generateTokensFromButtons(listStyleButtons(doc));
15194
+ if (generated.status !== "ready") return { tokens: null, nodes: [] };
15195
+ return { tokens: generated.tokens, nodes: styleTokenNodes(generated.tokens) };
15196
+ }
15197
+ function detectVariant(el, tokens) {
15198
+ const declared = declaredVariant(el.className || "");
15199
+ if (declared) return declared;
15200
+ const stamped = el.getAttribute("data-ohw-btn-variant");
15201
+ if (stamped && isButtonVariantId(stamped)) return stamped;
15202
+ const sample = readVariantSample(el);
15203
+ if (!tokens) return sampleSlot(sample);
15204
+ const key = fingerprint(sample);
15205
+ for (const id of BUTTON_VARIANT_IDS) {
15206
+ const chrome = tokens[id];
15207
+ const tokenKey = fingerprint({
15208
+ background: chrome.background,
15209
+ color: chrome.color,
15210
+ borderColor: chrome.borderColor,
15211
+ borderWidth: chrome.borderWidth,
15212
+ className: `btn btn--${id}`
15213
+ });
15214
+ if (tokenKey === key) return id;
15215
+ }
15216
+ return sampleSlot(sample);
15217
+ }
15218
+ function detectSize(el, tokens) {
15219
+ const stamped = el.getAttribute("data-ohw-btn-size");
15220
+ if (stamped && isButtonSizeId(stamped)) return stamped;
15221
+ const height = el.getBoundingClientRect().height;
15222
+ if (!tokens) return classifyHeight(height);
15223
+ let best = "m";
15224
+ let bestDelta = Number.POSITIVE_INFINITY;
15225
+ for (const id of BUTTON_SIZE_IDS) {
15226
+ const delta = Math.abs(tokens[id].height - height);
15227
+ if (delta < bestDelta) {
15228
+ best = id;
15229
+ bestDelta = delta;
15230
+ }
15231
+ }
15232
+ return best;
15233
+ }
15234
+ function assignmentFor(el, content, tokens) {
15235
+ const id = buttonId(el);
15236
+ const stored = id ? readAssignments(content)[id] : void 0;
15237
+ if (stored) return stored;
15238
+ return {
15239
+ variant: detectVariant(el, tokens?.variants ?? null),
15240
+ size: detectSize(el, tokens?.sizes ?? null)
15241
+ };
15242
+ }
15243
+ function labelElement(el) {
15244
+ return el.querySelector('[data-ohw-editable="text"], [data-ohw-editable="plain"]') ?? (el.matches('[data-ohw-editable="text"], [data-ohw-editable="plain"]') ? el : null);
15245
+ }
15246
+ function applyButtonStyle(el, assignment, tokens) {
15247
+ captureButtonOrigin(el);
15248
+ const chrome = tokens.variants[assignment.variant];
15249
+ const geometry = tokens.sizes[assignment.size];
15250
+ el.setAttribute("data-ohw-btn-variant", assignment.variant);
15251
+ el.setAttribute("data-ohw-btn-size", assignment.size);
15252
+ el.style.boxSizing = "border-box";
15253
+ el.style.display = "inline-flex";
15254
+ el.style.alignItems = "center";
15255
+ el.style.justifyContent = "center";
15256
+ el.style.background = chrome.background;
15257
+ el.style.color = chrome.color;
15258
+ el.style.borderStyle = parseFloat(chrome.borderWidth) > 0 ? "solid" : "none";
15259
+ el.style.borderColor = chrome.borderColor;
15260
+ el.style.borderWidth = chrome.borderWidth;
15261
+ el.style.padding = `${geometry.paddingTop} ${geometry.paddingRight} ${geometry.paddingBottom} ${geometry.paddingLeft}`;
15262
+ el.style.fontSize = geometry.fontSize;
15263
+ el.style.borderRadius = geometry.borderRadius;
15264
+ el.style.gap = geometry.gap;
15265
+ el.style.height = px(geometry.height);
15266
+ const label = labelElement(el);
15267
+ if (label && label !== el) label.style.color = chrome.color;
15268
+ }
15269
+ function applyButtonStylesFromContent(doc, content) {
15270
+ const assignments = readAssignments(content);
15271
+ for (const [id, assignment] of Object.entries(assignments)) {
15272
+ const el = doc.querySelector(`[data-ohw-href-key="${CSS.escape(id)}"]`);
15273
+ if (!el) continue;
15274
+ applyButtonStyle(el, assignment, tokensFromButton(el));
15275
+ }
15276
+ }
15277
+ function withAssignment(content, id, assignment) {
15278
+ return { ...readAssignments(content), [id]: assignment };
15279
+ }
15280
+
15281
+ // src/ui/button-style-panel.tsx
15282
+ var import_jsx_runtime29 = require("react/jsx-runtime");
15283
+ var SIZE_LABEL = { s: "S", m: "M", l: "L" };
15284
+ function ButtonStylePanel({
15285
+ variants,
15286
+ sizes,
15287
+ variant,
15288
+ size,
15289
+ onVariant,
15290
+ onSize,
15291
+ previewLabel = "Book Now",
15292
+ slotBackground = "var(--brand-background, var(--ohw-brand-light, var(--color-light, #ffffff)))"
15293
+ }) {
15294
+ const preview = scaleGeometry(sizes.m, 0.75);
15295
+ const label = previewLabel.trim() || "Book Now";
15296
+ return /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)("div", { className: "flex w-full flex-col gap-5", children: [
15297
+ /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)("section", { className: "flex w-full flex-col gap-2.5", children: [
15298
+ /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("h3", { className: "text-xs font-semibold uppercase leading-4 tracking-[0.6px] text-muted-foreground", children: "Variants" }),
15299
+ /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("div", { className: "flex w-full flex-col gap-2.5", children: BUTTON_VARIANT_IDS.map((id) => {
15300
+ const chrome = variants[id];
15301
+ const selected = id === variant;
15302
+ const hasBorder = parseFloat(chrome.borderWidth) > 0;
15303
+ return /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)(
15304
+ "button",
15305
+ {
15306
+ type: "button",
15307
+ "aria-pressed": selected,
15308
+ "aria-label": id,
15309
+ onMouseDown: (e) => {
15310
+ e.preventDefault();
15311
+ e.stopPropagation();
15312
+ },
15313
+ onClick: () => onVariant(id),
15314
+ className: cn(
15315
+ "relative w-full overflow-hidden rounded-xl border-solid text-left",
15316
+ selected ? "border-2 border-primary" : "border border-border"
15317
+ ),
15318
+ children: [
15319
+ /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
15320
+ "div",
15321
+ {
15322
+ className: "flex w-full items-center justify-center py-5",
15323
+ style: { background: slotBackground },
15324
+ children: /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
15325
+ "span",
15326
+ {
15327
+ className: "inline-flex items-center justify-center whitespace-nowrap font-semibold uppercase leading-none",
15328
+ style: {
15329
+ background: chrome.background,
15330
+ color: chrome.color,
15331
+ borderColor: chrome.borderColor,
15332
+ borderWidth: hasBorder ? chrome.borderWidth : "0px",
15333
+ borderStyle: hasBorder ? "solid" : "none",
15334
+ padding: `${preview.paddingTop} ${preview.paddingRight} ${preview.paddingBottom} ${preview.paddingLeft}`,
15335
+ fontSize: preview.fontSize,
15336
+ borderRadius: preview.borderRadius,
15337
+ height: preview.height,
15338
+ boxSizing: "border-box",
15339
+ letterSpacing: "0.12em"
15340
+ },
15341
+ children: label
15342
+ }
15343
+ )
15344
+ }
15345
+ ),
15346
+ selected ? /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
15347
+ "span",
15348
+ {
15349
+ className: "absolute right-0.5 top-0.5 flex size-5 items-center justify-center rounded-full bg-primary text-primary-foreground",
15350
+ "aria-hidden": true,
15351
+ children: /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(import_lucide_react15.Check, { className: "size-3", strokeWidth: 3 })
15352
+ }
15353
+ ) : null
15354
+ ]
15355
+ },
15356
+ id
15357
+ );
15358
+ }) })
15359
+ ] }),
15360
+ /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)("section", { className: "flex w-full flex-col gap-2.5", children: [
15361
+ /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("h3", { className: "text-xs font-semibold uppercase leading-4 tracking-[0.6px] text-muted-foreground", children: "Size" }),
15362
+ /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
15363
+ "div",
15364
+ {
15365
+ className: "flex w-full items-start rounded-lg bg-accent p-1",
15366
+ role: "radiogroup",
15367
+ "aria-label": "Size",
15368
+ children: BUTTON_SIZE_IDS.map((id) => {
15369
+ const selected = id === size;
15370
+ return /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
15371
+ "button",
15372
+ {
15373
+ type: "button",
15374
+ role: "radio",
15375
+ "aria-checked": selected,
15376
+ onMouseDown: (e) => {
15377
+ e.preventDefault();
15378
+ e.stopPropagation();
15379
+ },
15380
+ onClick: () => onSize(id),
15381
+ className: cn(
15382
+ "flex min-w-14 flex-1 items-center justify-center rounded-md px-3 py-1.5 text-sm font-medium leading-5",
15383
+ selected ? "bg-background text-foreground shadow-sm" : "bg-transparent text-muted-foreground"
15384
+ ),
15385
+ children: SIZE_LABEL[id]
15386
+ },
15387
+ id
15388
+ );
15389
+ })
15390
+ }
15391
+ )
15392
+ ] })
15393
+ ] });
15394
+ }
15395
+
15396
+ // src/lib/button-collections.ts
15397
+ var BUTTON_COLLECTIONS_KEY = "__ohw_button_collections";
15398
+ var BUTTON_SNAPSHOTS_KEY = "__ohw_button_snapshots";
15399
+ var BUTTON_HIDDEN_KEY = "__ohw_button_hidden";
15400
+ var COLLECTION_ATTR = "data-ohw-button-collection";
15401
+ function parseJson2(raw) {
15402
+ if (!raw) return null;
15403
+ try {
15404
+ return JSON.parse(raw);
15405
+ } catch {
15406
+ return null;
15407
+ }
15408
+ }
15409
+ function readCollections(content) {
15410
+ const parsed = parseJson2(content[BUTTON_COLLECTIONS_KEY]);
15411
+ if (!parsed || typeof parsed !== "object") return {};
15412
+ const next = {};
15413
+ for (const [id, value] of Object.entries(parsed)) {
15414
+ if (!value || !Array.isArray(value.members)) continue;
15415
+ next[id] = {
15416
+ id,
15417
+ members: value.members.filter((member) => typeof member === "string" && member),
15418
+ gap: typeof value.gap === "string" ? value.gap : "12px"
15419
+ };
15420
+ }
15421
+ return next;
15422
+ }
15423
+ function readSnapshots(content) {
15424
+ const parsed = parseJson2(content[BUTTON_SNAPSHOTS_KEY]);
15425
+ if (!parsed || typeof parsed !== "object") return {};
15426
+ const next = {};
15427
+ for (const [id, value] of Object.entries(parsed)) {
15428
+ if (!value || typeof value.html !== "string") continue;
15429
+ next[id] = value;
15430
+ }
15431
+ return next;
15432
+ }
15433
+ function readHiddenButtons(content) {
15434
+ const parsed = parseJson2(content[BUTTON_HIDDEN_KEY]);
15435
+ if (!Array.isArray(parsed)) return [];
15436
+ return parsed.filter((id) => typeof id === "string" && id);
15437
+ }
15438
+ function buttonCollectionOf(el) {
15439
+ return el?.closest(`[${COLLECTION_ATTR}]`) ?? null;
15440
+ }
15441
+ function isNavbarCta(el) {
15442
+ return el.getAttribute("data-ohw-role") === "navbar-button" || Boolean(el.closest('[data-ohw-role="navbar-button"]'));
15443
+ }
15444
+ function navbarScope(el) {
15445
+ return el.closest("nav, [data-ohw-nav-container], [data-ohw-nav-drawer]") ?? el.ownerDocument;
15446
+ }
15447
+ function isLastNavbarButton(el) {
15448
+ if (!isNavbarCta(el)) return false;
15449
+ const buttons = Array.from(navbarScope(el).querySelectorAll(CTA_BUTTON_SELECTOR)).filter(
15450
+ (button) => isNavbarCta(button) && buttonId(button)
15451
+ );
15452
+ return buttons.length <= 1;
15453
+ }
15454
+ function canDeleteButton(el) {
15455
+ return !isLastNavbarButton(el);
15456
+ }
15457
+ function labelElement2(el) {
15458
+ return el.querySelector('[data-ohw-editable="text"], [data-ohw-editable="plain"]') ?? el.querySelector("[data-ohw-key]");
15459
+ }
15460
+ function buttonLabel(el) {
15461
+ return (labelElement2(el)?.textContent ?? el.textContent ?? "").trim();
15462
+ }
15463
+ function buttonHref(el) {
15464
+ return el.getAttribute("href") ?? "";
15465
+ }
15466
+ function hrefKeyBase(hrefKey) {
15467
+ return hrefKey.replace(/-href$/, "").replace(/-copy-\d+$/, "");
15468
+ }
15469
+ function labelKeyForHrefKey(hrefKey) {
15470
+ return `${hrefKey.replace(/-href$/, "")}-label`;
15471
+ }
15472
+ function cleanClone(el) {
15473
+ const copy = el.cloneNode(true);
15474
+ copy.querySelectorAll("[data-ohw-selected], [data-ohw-hovered], [data-ohw-editing]").forEach((node) => {
15475
+ node.removeAttribute("data-ohw-selected");
15476
+ node.removeAttribute("data-ohw-hovered");
15477
+ node.removeAttribute("data-ohw-editing");
15478
+ node.removeAttribute("contenteditable");
15479
+ });
15480
+ copy.removeAttribute("data-ohw-selected");
15481
+ copy.removeAttribute("data-ohw-hovered");
15482
+ copy.removeAttribute("data-ohw-editing");
15483
+ copy.removeAttribute("contenteditable");
15484
+ copy.removeAttribute("data-ohw-drag-disabled");
15485
+ return copy;
15486
+ }
15487
+ function nextCopyId(sourceId, content, doc) {
15488
+ const used = /* @__PURE__ */ new Set([
15489
+ ...Object.keys(readSnapshots(content)),
15490
+ ...Object.keys(readAssignments(content)),
15491
+ ...Array.from(doc.querySelectorAll("[data-ohw-href-key]")).map(
15492
+ (el) => el.getAttribute("data-ohw-href-key") ?? ""
15493
+ )
15494
+ ]);
15495
+ const base = hrefKeyBase(sourceId);
15496
+ let n = 2;
15497
+ while (used.has(`${base}-copy-${n}-href`)) n += 1;
15498
+ return `${base}-copy-${n}-href`;
15499
+ }
15500
+ function nextCollectionId(content, doc) {
15501
+ const used = /* @__PURE__ */ new Set([
15502
+ ...Object.keys(readCollections(content)),
15503
+ ...Array.from(doc.querySelectorAll(`[${COLLECTION_ATTR}]`)).map(
15504
+ (el) => el.getAttribute(COLLECTION_ATTR) ?? ""
15505
+ )
15506
+ ]);
15507
+ let n = 1;
15508
+ while (used.has(`bc-${n}`)) n += 1;
15509
+ return `bc-${n}`;
15510
+ }
15511
+ function collectionGap(el, tokens) {
15512
+ if (tokens) return tokens.sizes.m.gap;
15513
+ const parent = el.parentElement;
15514
+ if (!parent) return "12px";
15515
+ const gap = getComputedStyle(parent).columnGap || getComputedStyle(parent).gap;
15516
+ return gap && gap !== "normal" ? gap : "12px";
15517
+ }
15518
+ function styleCollection(collection, gap) {
15519
+ collection.style.display = "inline-flex";
15520
+ collection.style.alignItems = "center";
15521
+ collection.style.flexWrap = "wrap";
15522
+ collection.style.gap = gap;
15523
+ collection.style.maxWidth = "100%";
15524
+ }
15525
+ function createCollection(doc, id, gap) {
15526
+ const collection = doc.createElement("div");
15527
+ collection.setAttribute(COLLECTION_ATTR, id);
15528
+ styleCollection(collection, gap);
15529
+ return collection;
15530
+ }
15531
+ function setButtonDragAttr(el) {
15532
+ if (isNavbarCta(el) && buttonCollectionOf(el)) el.removeAttribute("data-ohw-drag-disabled");
15533
+ else el.setAttribute("data-ohw-drag-disabled", "true");
15534
+ }
15535
+ function rekeyCopy(copy, id) {
15536
+ copy.setAttribute("data-ohw-href-key", id);
15537
+ const label = labelElement2(copy);
15538
+ const labelKey = labelKeyForHrefKey(id);
15539
+ if (label) label.setAttribute("data-ohw-key", labelKey);
15540
+ setButtonDragAttr(copy);
15541
+ return { labelKey };
15542
+ }
15543
+ function snapshotOf(el) {
15544
+ const id = buttonId(el) ?? "";
15545
+ const label = labelElement2(el);
15546
+ return {
15547
+ id,
15548
+ href: buttonHref(el),
15549
+ label: buttonLabel(el),
15550
+ labelKey: label?.getAttribute("data-ohw-key") ?? labelKeyForHrefKey(id),
15551
+ html: cleanClone(el).outerHTML
15552
+ };
15553
+ }
15554
+ function htmlToElement(doc, html) {
15555
+ const wrap = doc.createElement("div");
15556
+ wrap.innerHTML = html;
15557
+ const el = wrap.firstElementChild;
15558
+ return el instanceof HTMLElement ? el : null;
15559
+ }
15560
+ function findButton(doc, id) {
15561
+ return doc.querySelector(`[data-ohw-href-key="${CSS.escape(id)}"]`);
15562
+ }
15563
+ function duplicateButton(source, content) {
15564
+ const sourceId = buttonId(source);
15565
+ if (!sourceId) return null;
15566
+ const doc = source.ownerDocument;
15567
+ const tokens = tokensFromButton(source);
15568
+ const copyId = nextCopyId(sourceId, content, doc);
15569
+ const copy = cleanClone(source);
15570
+ const { labelKey } = rekeyCopy(copy, copyId);
15571
+ const href = buttonHref(source);
15572
+ const label = buttonLabel(source);
15573
+ if (href) copy.setAttribute("href", href);
15574
+ const assignment = readAssignments(content)[sourceId];
15575
+ if (assignment) applyButtonStyle(copy, assignment, tokens);
15576
+ const copyLabelEl = labelElement2(copy);
15577
+ if (copyLabelEl) copyLabelEl.textContent = label;
15578
+ let collection = buttonCollectionOf(source);
15579
+ const collections = readCollections(content);
15580
+ let collectionId = collection?.getAttribute(COLLECTION_ATTR) ?? "";
15581
+ let members = collectionId && collections[collectionId] ? [...collections[collectionId].members] : [];
15582
+ const gap = collection?.style.gap || collectionGap(source, tokens);
15583
+ if (!collection) {
15584
+ collectionId = nextCollectionId(content, doc);
15585
+ collection = createCollection(doc, collectionId, gap);
15586
+ source.parentElement?.insertBefore(collection, source);
15587
+ collection.append(source, copy);
15588
+ setButtonDragAttr(source);
15589
+ setButtonDragAttr(copy);
15590
+ members = [sourceId, copyId];
15591
+ } else {
15592
+ styleCollection(collection, gap);
15593
+ source.after(copy);
15594
+ setButtonDragAttr(copy);
15595
+ if (!members.includes(sourceId)) members = listCollectionMembers(collection);
15596
+ const at = members.indexOf(sourceId);
15597
+ members.splice(at >= 0 ? at + 1 : members.length, 0, copyId);
15598
+ }
15599
+ const sourceLabelKey = labelElement2(source)?.getAttribute("data-ohw-key");
15600
+ const snapshots = {
15601
+ ...readSnapshots(content),
15602
+ [sourceId]: snapshotOf(source),
15603
+ [copyId]: snapshotOf(copy)
15604
+ };
15605
+ const nextCollections = {
15606
+ ...collections,
15607
+ [collectionId]: { id: collectionId, members, gap }
15608
+ };
15609
+ const assignments = assignment ? withAssignment(content, copyId, assignment) : readAssignments(content);
15610
+ const nextContent = {
15611
+ ...content,
15612
+ [copyId]: href,
15613
+ [labelKey]: label,
15614
+ [BUTTON_COLLECTIONS_KEY]: JSON.stringify(nextCollections),
15615
+ [BUTTON_SNAPSHOTS_KEY]: JSON.stringify(snapshots)
15616
+ };
15617
+ if (sourceLabelKey && nextContent[sourceLabelKey] === void 0) {
15618
+ nextContent[sourceLabelKey] = label;
15619
+ }
15620
+ if (Object.keys(assignments).length > 0) {
15621
+ nextContent[BUTTON_ASSIGNMENTS_KEY] = JSON.stringify(assignments);
15622
+ }
15623
+ const nodeKeys = [
15624
+ copyId,
15625
+ labelKey,
15626
+ BUTTON_COLLECTIONS_KEY,
15627
+ BUTTON_SNAPSHOTS_KEY,
15628
+ BUTTON_ASSIGNMENTS_KEY
15629
+ ];
15630
+ if (sourceLabelKey) nodeKeys.push(sourceLabelKey);
15631
+ return {
15632
+ copy,
15633
+ content: nextContent,
15634
+ nodes: contentNodes(nextContent, nodeKeys)
15635
+ };
15636
+ }
15637
+ function listCollectionMembers(collection) {
15638
+ return Array.from(collection.querySelectorAll(CTA_BUTTON_SELECTOR)).map((el) => buttonId(el)).filter((id) => Boolean(id));
15639
+ }
15640
+ function contentNodes(content, keys) {
15641
+ return keys.filter((key) => content[key] !== void 0).map((key) => ({ key, text: content[key] }));
15642
+ }
15643
+ function deleteButton(source, content) {
15644
+ if (!canDeleteButton(source)) return null;
15645
+ const id = buttonId(source);
15646
+ if (!id) return null;
15647
+ const parent = source.parentElement;
15648
+ const nextSibling = source.nextSibling;
15649
+ const removed = source;
15650
+ const collection = buttonCollectionOf(source);
15651
+ const collectionId = collection?.getAttribute(COLLECTION_ATTR) ?? "";
15652
+ const previousCollections = readCollections(content);
15653
+ const previousHidden = readHiddenButtons(content);
15654
+ const snapshots = { ...readSnapshots(content) };
15655
+ const assignments = { ...readAssignments(content) };
15656
+ delete assignments[id];
15657
+ const remainingBeforeUnwrap = collection ? listCollectionMembers(collection).filter((member) => member !== id) : [];
15658
+ removed.remove();
15659
+ let nextCollections = { ...previousCollections };
15660
+ let unwrapped = null;
15661
+ if (collection && collectionId) {
15662
+ const members = listCollectionMembers(collection);
15663
+ if (members.length <= 1) {
15664
+ unwrapped = collection;
15665
+ unwrapCollection(collection);
15666
+ delete nextCollections[collectionId];
15667
+ } else {
15668
+ nextCollections[collectionId] = {
15669
+ id: collectionId,
15670
+ members,
15671
+ gap: collection.style.gap || previousCollections[collectionId]?.gap || "12px"
15672
+ };
15673
+ }
15674
+ }
15675
+ const hidden = previousHidden.includes(id) ? previousHidden : [...previousHidden, id];
15676
+ const nextContent = {
15677
+ ...content,
15678
+ [id]: "",
15679
+ [BUTTON_COLLECTIONS_KEY]: JSON.stringify(nextCollections),
15680
+ [BUTTON_HIDDEN_KEY]: JSON.stringify(hidden),
15681
+ [BUTTON_SNAPSHOTS_KEY]: JSON.stringify(snapshots),
15682
+ [BUTTON_ASSIGNMENTS_KEY]: JSON.stringify(assignments)
15683
+ };
15684
+ return {
15685
+ content: nextContent,
15686
+ nodes: contentNodes(nextContent, [id, BUTTON_COLLECTIONS_KEY, BUTTON_HIDDEN_KEY, BUTTON_SNAPSHOTS_KEY, BUTTON_ASSIGNMENTS_KEY]),
15687
+ undo: () => {
15688
+ if (unwrapped && remainingBeforeUnwrap.length === 1) {
15689
+ const remaining = findButton(removed.ownerDocument, remainingBeforeUnwrap[0]);
15690
+ const host = remaining?.parentElement;
15691
+ if (remaining && host) {
15692
+ const restoredCollection = createCollection(
15693
+ removed.ownerDocument,
15694
+ collectionId,
15695
+ previousCollections[collectionId]?.gap || "12px"
15696
+ );
15697
+ host.insertBefore(restoredCollection, remaining);
15698
+ restoredCollection.append(remaining, removed);
15699
+ return;
15700
+ }
15701
+ }
15702
+ if (nextSibling && nextSibling.parentNode === parent) parent?.insertBefore(removed, nextSibling);
15703
+ else parent?.appendChild(removed);
15704
+ }
15705
+ };
15706
+ }
15707
+ function unwrapCollection(collection) {
15708
+ const parent = collection.parentElement;
15709
+ if (!parent) return;
15710
+ while (collection.firstChild) parent.insertBefore(collection.firstChild, collection);
15711
+ collection.remove();
15712
+ }
15713
+ function reorderButtonInCollection(button, clientX) {
15714
+ const collection = buttonCollectionOf(button);
15715
+ const id = buttonId(button);
15716
+ if (!collection || !id) return null;
15717
+ const siblings = Array.from(collection.querySelectorAll(CTA_BUTTON_SELECTOR)).filter((el) => el !== button);
15718
+ let placed = false;
15719
+ for (const sibling of siblings) {
15720
+ const rect = sibling.getBoundingClientRect();
15721
+ if (clientX < rect.left + rect.width / 2) {
15722
+ sibling.before(button);
15723
+ placed = true;
15724
+ break;
15725
+ }
15726
+ }
15727
+ if (!placed) collection.append(button);
15728
+ return listCollectionMembers(collection);
15729
+ }
15730
+ function persistCollectionOrder(collection, content) {
15731
+ const id = collection.getAttribute(COLLECTION_ATTR);
15732
+ if (!id) return null;
15733
+ const collections = readCollections(content);
15734
+ const current = collections[id];
15735
+ const members = listCollectionMembers(collection);
15736
+ const next = {
15737
+ ...collections,
15738
+ [id]: { id, members, gap: collection.style.gap || current?.gap || "12px" }
15739
+ };
15740
+ const nextContent = { ...content, [BUTTON_COLLECTIONS_KEY]: JSON.stringify(next) };
15741
+ return { content: nextContent, nodes: [{ key: BUTTON_COLLECTIONS_KEY, text: nextContent[BUTTON_COLLECTIONS_KEY] }] };
15742
+ }
15743
+ function hideButton(el) {
15744
+ if (el.getAttribute("data-ohw-button-hidden") === "") return;
15745
+ el.setAttribute("data-ohw-button-hidden", "");
15746
+ el.style.display = "none";
15747
+ }
15748
+ function syncButtonsFromContent(doc, content) {
15749
+ reconcileButtonCollections(doc, content);
15750
+ applyButtonContentFromContent(doc, content);
15751
+ applyButtonStylesFromContent(doc, content);
15752
+ }
15753
+ function applyButtonContentFromContent(doc, content) {
15754
+ const snapshots = readSnapshots(content);
15755
+ for (const snapshot of Object.values(snapshots)) {
15756
+ const el = findButton(doc, snapshot.id);
15757
+ if (!el) continue;
15758
+ applySnapshotContent(el, snapshot, content);
15759
+ }
15760
+ }
15761
+ function applySnapshotContent(el, snapshot, content) {
15762
+ const href = content[snapshot.id] ?? snapshot.href;
15763
+ if (href) el.setAttribute("href", href);
15764
+ const labelKey = snapshot.labelKey || labelKeyForHrefKey(snapshot.id);
15765
+ if (labelKey && !el.querySelector(`[data-ohw-key="${CSS.escape(labelKey)}"]`)) {
15766
+ const label2 = labelElement2(el);
15767
+ if (label2) label2.setAttribute("data-ohw-key", labelKey);
15768
+ }
15769
+ const text = content[labelKey];
15770
+ if (text === void 0) return;
15771
+ const label = labelElement2(el);
15772
+ if (label) {
15773
+ if (label.getAttribute("data-ohw-key") !== labelKey) label.setAttribute("data-ohw-key", labelKey);
15774
+ if (label.textContent !== text) label.textContent = text;
15775
+ }
15776
+ }
15777
+ function reconcileButtonCollections(doc, content) {
15778
+ const hidden = new Set(readHiddenButtons(content));
15779
+ for (const id of hidden) {
15780
+ const el = findButton(doc, id);
15781
+ if (el) hideButton(el);
15782
+ }
15783
+ const snapshots = readSnapshots(content);
15784
+ const collections = readCollections(content);
15785
+ for (const collectionState of Object.values(collections)) {
15786
+ const live = collectionState.members.map((id) => findButton(doc, id) ?? restoreSnapshot(doc, snapshots[id], content)).filter((el) => Boolean(el && !hidden.has(buttonId(el) ?? "")));
15787
+ if (live.length === 0) continue;
15788
+ if (live.length === 1) {
15789
+ const existing = buttonCollectionOf(live[0]);
15790
+ if (existing) unwrapCollection(existing);
15791
+ continue;
15792
+ }
15793
+ const anchor = live.find((el) => el.isConnected) ?? live[0];
15794
+ let collection = live.map((el) => buttonCollectionOf(el)).find((el) => el?.getAttribute(COLLECTION_ATTR) === collectionState.id) ?? null;
15795
+ if (!collection) {
15796
+ if (!anchor.parentElement) continue;
15797
+ collection = createCollection(doc, collectionState.id, collectionState.gap);
15798
+ anchor.parentElement.insertBefore(collection, anchor);
15799
+ }
15800
+ styleCollection(collection, collectionState.gap);
15801
+ const current = listCollectionMembers(collection);
15802
+ const sameOrder = current.length === live.length && current.every((id, index) => id === buttonId(live[index]));
15803
+ if (!sameOrder) {
15804
+ for (const member of live) collection.append(member);
15805
+ }
15806
+ for (const member of live) setButtonDragAttr(member);
15807
+ }
15808
+ }
15809
+ function restoreSnapshot(doc, snapshot, content) {
15810
+ if (!snapshot) return null;
15811
+ const existing = findButton(doc, snapshot.id);
15812
+ if (existing) {
15813
+ applySnapshotContent(existing, snapshot, content);
15814
+ return existing;
15815
+ }
15816
+ const el = htmlToElement(doc, snapshot.html);
15817
+ if (!el) return null;
15818
+ el.setAttribute("data-ohw-href-key", snapshot.id);
15819
+ const label = labelElement2(el);
15820
+ const labelKey = snapshot.labelKey || labelKeyForHrefKey(snapshot.id);
15821
+ if (label) label.setAttribute("data-ohw-key", labelKey);
15822
+ applySnapshotContent(el, snapshot, content);
15823
+ setButtonDragAttr(el);
15824
+ return el;
15825
+ }
15826
+ function collectionDragEnabled(el) {
15827
+ return Boolean(isNavbarCta(el) && buttonCollectionOf(el) && buttonId(el));
15828
+ }
15829
+
14654
15830
  // src/lib/item-drag-interaction.ts
14655
15831
  function disableNativeHrefDrag(el) {
14656
15832
  if (el.draggable) el.draggable = false;
@@ -15637,8 +16813,8 @@ function useSectionDrag({
15637
16813
  }
15638
16814
 
15639
16815
  // src/ui/footer-container-chrome.tsx
15640
- var import_lucide_react15 = require("lucide-react");
15641
- var import_jsx_runtime29 = require("react/jsx-runtime");
16816
+ var import_lucide_react16 = require("lucide-react");
16817
+ var import_jsx_runtime30 = require("react/jsx-runtime");
15642
16818
  function FooterContainerChrome({
15643
16819
  rect,
15644
16820
  onAdd,
@@ -15646,7 +16822,7 @@ function FooterContainerChrome({
15646
16822
  }) {
15647
16823
  const chromeGap = 6;
15648
16824
  const buttonMargin = 7;
15649
- return /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(TooltipProvider, { delayDuration: 0, children: /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
16825
+ return /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(TooltipProvider, { delayDuration: 0, children: /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
15650
16826
  "div",
15651
16827
  {
15652
16828
  "data-ohw-footer-container-chrome": "",
@@ -15658,8 +16834,8 @@ function FooterContainerChrome({
15658
16834
  width: rect.width + chromeGap * 2,
15659
16835
  height: rect.height + chromeGap * 2
15660
16836
  },
15661
- children: /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)(Tooltip, { children: [
15662
- /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
16837
+ children: /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)(Tooltip, { children: [
16838
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
15663
16839
  "button",
15664
16840
  {
15665
16841
  type: "button",
@@ -15678,10 +16854,10 @@ function FooterContainerChrome({
15678
16854
  if (addDisabled) return;
15679
16855
  onAdd();
15680
16856
  },
15681
- children: /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(import_lucide_react15.Plus, { className: "size-4 shrink-0 text-foreground", "aria-hidden": true })
16857
+ children: /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(import_lucide_react16.Plus, { className: "size-4 shrink-0 text-foreground", "aria-hidden": true })
15682
16858
  }
15683
16859
  ) }),
15684
- /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(TooltipContent, { side: "bottom", sideOffset: 9, children: addDisabled ? "Maximum columns reached" : "Add item" })
16860
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(TooltipContent, { side: "bottom", sideOffset: 9, children: addDisabled ? "Maximum columns reached" : "Add item" })
15685
16861
  ] })
15686
16862
  }
15687
16863
  ) });
@@ -16163,14 +17339,14 @@ function deleteSelectedNavFooterItem(deps) {
16163
17339
  }
16164
17340
 
16165
17341
  // src/ui/navbar-container-chrome.tsx
16166
- var import_lucide_react16 = require("lucide-react");
16167
- var import_jsx_runtime30 = require("react/jsx-runtime");
17342
+ var import_lucide_react17 = require("lucide-react");
17343
+ var import_jsx_runtime31 = require("react/jsx-runtime");
16168
17344
  function NavbarContainerChrome({
16169
17345
  rect,
16170
17346
  onAdd
16171
17347
  }) {
16172
17348
  const chromeGap = 6;
16173
- return /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
17349
+ return /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(
16174
17350
  "div",
16175
17351
  {
16176
17352
  "data-ohw-navbar-container-chrome": "",
@@ -16182,7 +17358,7 @@ function NavbarContainerChrome({
16182
17358
  width: rect.width + chromeGap * 2,
16183
17359
  height: rect.height + chromeGap * 2
16184
17360
  },
16185
- children: /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
17361
+ children: /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(
16186
17362
  "button",
16187
17363
  {
16188
17364
  type: "button",
@@ -16199,7 +17375,7 @@ function NavbarContainerChrome({
16199
17375
  e.stopPropagation();
16200
17376
  onAdd();
16201
17377
  },
16202
- children: /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(import_lucide_react16.Plus, { className: "size-4 shrink-0 text-foreground", "aria-hidden": true })
17378
+ children: /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(import_lucide_react17.Plus, { className: "size-4 shrink-0 text-foreground", "aria-hidden": true })
16203
17379
  }
16204
17380
  )
16205
17381
  }
@@ -16208,7 +17384,7 @@ function NavbarContainerChrome({
16208
17384
 
16209
17385
  // src/ui/drop-indicator.tsx
16210
17386
  var React11 = __toESM(require("react"), 1);
16211
- var import_jsx_runtime31 = require("react/jsx-runtime");
17387
+ var import_jsx_runtime32 = require("react/jsx-runtime");
16212
17388
  var dropIndicatorVariants = cva(
16213
17389
  "ov-gap-line pointer-events-none shrink-0 transition-opacity duration-150",
16214
17390
  {
@@ -16232,7 +17408,7 @@ var dropIndicatorVariants = cva(
16232
17408
  );
16233
17409
  var DropIndicator = React11.forwardRef(
16234
17410
  ({ className, direction, state, ...props }, ref) => {
16235
- return /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(
17411
+ return /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
16236
17412
  "div",
16237
17413
  {
16238
17414
  ref,
@@ -16249,7 +17425,7 @@ var DropIndicator = React11.forwardRef(
16249
17425
  DropIndicator.displayName = "DropIndicator";
16250
17426
 
16251
17427
  // src/ui/badge.tsx
16252
- var import_jsx_runtime32 = require("react/jsx-runtime");
17428
+ var import_jsx_runtime33 = require("react/jsx-runtime");
16253
17429
  var badgeVariants = cva(
16254
17430
  "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",
16255
17431
  {
@@ -16267,12 +17443,12 @@ var badgeVariants = cva(
16267
17443
  }
16268
17444
  );
16269
17445
  function Badge({ className, variant, ...props }) {
16270
- return /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("div", { className: cn(badgeVariants({ variant }), className), ...props });
17446
+ return /* @__PURE__ */ (0, import_jsx_runtime33.jsx)("div", { className: cn(badgeVariants({ variant }), className), ...props });
16271
17447
  }
16272
17448
 
16273
17449
  // src/OhhwellsBridge.tsx
16274
- var import_lucide_react17 = require("lucide-react");
16275
- var import_jsx_runtime33 = require("react/jsx-runtime");
17450
+ var import_lucide_react18 = require("lucide-react");
17451
+ var import_jsx_runtime34 = require("react/jsx-runtime");
16276
17452
  var PRIMARY3 = "#0885FE";
16277
17453
  var IMAGE_FADE_MS = 300;
16278
17454
  var MEDIA_SETTLE_TIMEOUT_MS = 2500;
@@ -16394,7 +17570,7 @@ function duplicateSchedulingWidget(instanceId, scheduleId) {
16394
17570
  schedulingRoots.set(container, root);
16395
17571
  (0, import_react_dom4.flushSync)(() => {
16396
17572
  root.render(
16397
- /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
17573
+ /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
16398
17574
  SchedulingWidget,
16399
17575
  {
16400
17576
  notifyOnConnect: false,
@@ -16522,7 +17698,7 @@ function mountSchedulingWidget(anchorId, notifyOnConnect = false, scheduleId, be
16522
17698
  schedulingRoots.set(container, root);
16523
17699
  (0, import_react_dom4.flushSync)(() => {
16524
17700
  root.render(
16525
- /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
17701
+ /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
16526
17702
  SchedulingWidget,
16527
17703
  {
16528
17704
  notifyOnConnect,
@@ -16693,8 +17869,8 @@ function lockVideoBox(video) {
16693
17869
  }
16694
17870
  const fit = video.style.objectFit || getComputedStyle(video).objectFit;
16695
17871
  const bg = getComputedStyle(video).backgroundColor;
16696
- const isTransparent = bg === "rgba(0, 0, 0, 0)" || bg === "transparent" || !bg;
16697
- if (fit === "contain" && isTransparent) {
17872
+ const isTransparent2 = bg === "rgba(0, 0, 0, 0)" || bg === "transparent" || !bg;
17873
+ if (fit === "contain" && isTransparent2) {
16698
17874
  video.style.backgroundColor = "var(--color-dark, #000)";
16699
17875
  }
16700
17876
  }
@@ -16844,7 +18020,10 @@ function listNavigationItems() {
16844
18020
  ).filter((el) => isNavigationItem2(el));
16845
18021
  }
16846
18022
  function getNavigationItemReorderState(anchor) {
16847
- if (isCtaButton(anchor)) return { key: null, disabled: false };
18023
+ if (isCtaButton(anchor)) {
18024
+ if (!collectionDragEnabled(anchor)) return { key: null, disabled: true };
18025
+ return { key: buttonId(anchor), disabled: false };
18026
+ }
16848
18027
  return getReorderHandleStateFromAnchor(anchor);
16849
18028
  }
16850
18029
  function getReorderHandleState(el) {
@@ -17275,7 +18454,7 @@ function EditGlowChrome({
17275
18454
  hideHandle = false
17276
18455
  }) {
17277
18456
  const GAP = SELECTION_CHROME_GAP2;
17278
- return /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)(
18457
+ return /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)(
17279
18458
  "div",
17280
18459
  {
17281
18460
  ref: elRef,
@@ -17290,7 +18469,7 @@ function EditGlowChrome({
17290
18469
  zIndex: 2147483646
17291
18470
  },
17292
18471
  children: [
17293
- /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
18472
+ /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
17294
18473
  "div",
17295
18474
  {
17296
18475
  style: {
@@ -17304,7 +18483,7 @@ function EditGlowChrome({
17304
18483
  }
17305
18484
  }
17306
18485
  ),
17307
- reorderHrefKey && !hideHandle && /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
18486
+ reorderHrefKey && !hideHandle && /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
17308
18487
  "div",
17309
18488
  {
17310
18489
  "data-ohw-drag-handle-container": "",
@@ -17316,7 +18495,7 @@ function EditGlowChrome({
17316
18495
  transform: "translate(calc(-100% - 7px), -50%)",
17317
18496
  pointerEvents: dragDisabled ? "none" : "auto"
17318
18497
  },
17319
- children: /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
18498
+ children: /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
17320
18499
  DragHandle,
17321
18500
  {
17322
18501
  "aria-label": `Reorder ${reorderHrefKey}`,
@@ -17530,7 +18709,7 @@ function FloatingToolbar({
17530
18709
  return () => ro.disconnect();
17531
18710
  }, [showEditLink, activeCommands]);
17532
18711
  const { top, left, transform } = calcToolbarPos(rect, parentScroll, measuredW);
17533
- return /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
18712
+ return /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
17534
18713
  "div",
17535
18714
  {
17536
18715
  ref: setRefs,
@@ -17542,12 +18721,12 @@ function FloatingToolbar({
17542
18721
  zIndex: 2147483647,
17543
18722
  pointerEvents: "auto"
17544
18723
  },
17545
- children: /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)(CustomToolbar, { children: [
17546
- TOOLBAR_GROUPS.map((btns, gi) => /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)(import_react17.default.Fragment, { children: [
17547
- gi > 0 && /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(CustomToolbarDivider, {}),
18724
+ children: /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)(CustomToolbar, { children: [
18725
+ TOOLBAR_GROUPS.map((btns, gi) => /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)(import_react17.default.Fragment, { children: [
18726
+ gi > 0 && /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(CustomToolbarDivider, {}),
17548
18727
  btns.map((btn) => {
17549
18728
  const isActive = activeCommands.has(btn.cmd);
17550
- return /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
18729
+ return /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
17551
18730
  CustomToolbarButton,
17552
18731
  {
17553
18732
  title: btn.title,
@@ -17556,7 +18735,7 @@ function FloatingToolbar({
17556
18735
  e.preventDefault();
17557
18736
  onCommand(btn.cmd);
17558
18737
  },
17559
- children: /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
18738
+ children: /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
17560
18739
  "svg",
17561
18740
  {
17562
18741
  width: "16",
@@ -17577,7 +18756,7 @@ function FloatingToolbar({
17577
18756
  );
17578
18757
  })
17579
18758
  ] }, gi)),
17580
- showEditLink ? /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
18759
+ showEditLink ? /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
17581
18760
  CustomToolbarButton,
17582
18761
  {
17583
18762
  type: "button",
@@ -17591,7 +18770,7 @@ function FloatingToolbar({
17591
18770
  e.preventDefault();
17592
18771
  e.stopPropagation();
17593
18772
  },
17594
- children: /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(import_lucide_react17.Link, { className: "size-4 shrink-0", "aria-hidden": true })
18773
+ children: /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(import_lucide_react18.Link, { className: "size-4 shrink-0", "aria-hidden": true })
17595
18774
  }
17596
18775
  ) : null
17597
18776
  ] })
@@ -17608,7 +18787,7 @@ function StateToggle({
17608
18787
  states,
17609
18788
  onStateChange
17610
18789
  }) {
17611
- return /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
18790
+ return /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
17612
18791
  ToggleGroup,
17613
18792
  {
17614
18793
  "data-ohw-state-toggle": "",
@@ -17622,7 +18801,7 @@ function StateToggle({
17622
18801
  left: rect.right - 8,
17623
18802
  transform: "translateX(-100%)"
17624
18803
  },
17625
- children: states.map((state) => /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(ToggleGroupItem, { value: state, size: "sm", children: state }, state))
18804
+ children: states.map((state) => /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(ToggleGroupItem, { value: state, size: "sm", children: state }, state))
17626
18805
  }
17627
18806
  );
17628
18807
  }
@@ -17639,9 +18818,9 @@ var OHW_LOADER_STYLE = {
17639
18818
  justifyContent: "center"
17640
18819
  };
17641
18820
  function OhwLoaderSpinner() {
17642
- return /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)("svg", { width: "28", height: "28", viewBox: "0 0 28 28", fill: "none", "aria-hidden": true, children: [
17643
- /* @__PURE__ */ (0, import_jsx_runtime33.jsx)("circle", { cx: "14", cy: "14", r: "11", stroke: "#E7E5E4", strokeWidth: "3" }),
17644
- /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
18821
+ return /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)("svg", { width: "28", height: "28", viewBox: "0 0 28 28", fill: "none", "aria-hidden": true, children: [
18822
+ /* @__PURE__ */ (0, import_jsx_runtime34.jsx)("circle", { cx: "14", cy: "14", r: "11", stroke: "#E7E5E4", strokeWidth: "3" }),
18823
+ /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
17645
18824
  "circle",
17646
18825
  {
17647
18826
  cx: "14",
@@ -17651,7 +18830,7 @@ function OhwLoaderSpinner() {
17651
18830
  strokeWidth: "3",
17652
18831
  strokeDasharray: "17 52",
17653
18832
  strokeLinecap: "round",
17654
- children: /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
18833
+ children: /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
17655
18834
  "animateTransform",
17656
18835
  {
17657
18836
  attributeName: "transform",
@@ -17667,7 +18846,7 @@ function OhwLoaderSpinner() {
17667
18846
  ] });
17668
18847
  }
17669
18848
  function OhwBrandMark() {
17670
- return /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)(
18849
+ return /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)(
17671
18850
  "svg",
17672
18851
  {
17673
18852
  width: "16",
@@ -17678,7 +18857,7 @@ function OhwBrandMark() {
17678
18857
  style: { display: "block", flexShrink: 0 },
17679
18858
  xmlns: "http://www.w3.org/2000/svg",
17680
18859
  children: [
17681
- /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
18860
+ /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
17682
18861
  "mask",
17683
18862
  {
17684
18863
  id: "ohw-badge-mark",
@@ -17688,15 +18867,15 @@ function OhwBrandMark() {
17688
18867
  y: "0",
17689
18868
  width: "48",
17690
18869
  height: "48",
17691
- children: /* @__PURE__ */ (0, import_jsx_runtime33.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" })
18870
+ children: /* @__PURE__ */ (0, import_jsx_runtime34.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" })
17692
18871
  }
17693
18872
  ),
17694
- /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)("g", { mask: "url(#ohw-badge-mark)", children: [
17695
- /* @__PURE__ */ (0, import_jsx_runtime33.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" }),
17696
- /* @__PURE__ */ (0, import_jsx_runtime33.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" }),
17697
- /* @__PURE__ */ (0, import_jsx_runtime33.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" }),
17698
- /* @__PURE__ */ (0, import_jsx_runtime33.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" }),
17699
- /* @__PURE__ */ (0, import_jsx_runtime33.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" })
18873
+ /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)("g", { mask: "url(#ohw-badge-mark)", children: [
18874
+ /* @__PURE__ */ (0, import_jsx_runtime34.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" }),
18875
+ /* @__PURE__ */ (0, import_jsx_runtime34.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" }),
18876
+ /* @__PURE__ */ (0, import_jsx_runtime34.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" }),
18877
+ /* @__PURE__ */ (0, import_jsx_runtime34.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" }),
18878
+ /* @__PURE__ */ (0, import_jsx_runtime34.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" })
17700
18879
  ] })
17701
18880
  ]
17702
18881
  }
@@ -17733,7 +18912,7 @@ var OHW_BADGE_LABEL_STYLE = {
17733
18912
  whiteSpace: "nowrap"
17734
18913
  };
17735
18914
  function MadeWithOhhWells() {
17736
- return /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)(
18915
+ return /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)(
17737
18916
  "a",
17738
18917
  {
17739
18918
  href: "https://ohhwells.com",
@@ -17743,8 +18922,8 @@ function MadeWithOhhWells() {
17743
18922
  "data-ohw-badge": "",
17744
18923
  style: OHW_BADGE_STYLE,
17745
18924
  children: [
17746
- /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(OhwBrandMark, {}),
17747
- /* @__PURE__ */ (0, import_jsx_runtime33.jsx)("span", { style: OHW_BADGE_LABEL_STYLE, children: "Made with OhhWells" })
18925
+ /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(OhwBrandMark, {}),
18926
+ /* @__PURE__ */ (0, import_jsx_runtime34.jsx)("span", { style: OHW_BADGE_LABEL_STYLE, children: "Made with OhhWells" })
17748
18927
  ]
17749
18928
  }
17750
18929
  );
@@ -18251,8 +19430,12 @@ function OhhwellsBridge() {
18251
19430
  const pendingDeleteUndoRef = (0, import_react17.useRef)(null);
18252
19431
  const [floatingPanel, setFloatingPanel] = (0, import_react17.useState)(null);
18253
19432
  const floatingPanelOpenRef = (0, import_react17.useRef)(false);
19433
+ const floatingPanelRef = (0, import_react17.useRef)(null);
19434
+ floatingPanelRef.current = floatingPanel;
18254
19435
  const setFloatingPanelRef = (0, import_react17.useRef)(setFloatingPanel);
18255
19436
  const [floatingPanelPos, setFloatingPanelPos] = (0, import_react17.useState)(null);
19437
+ const buttonCollectionDragRef = (0, import_react17.useRef)(null);
19438
+ const [buttonStyleTick, setButtonStyleTick] = (0, import_react17.useState)(0);
18256
19439
  const [logoSizeDraft, setLogoSizeDraft] = (0, import_react17.useState)(null);
18257
19440
  const [editorViewport, setEditorViewport] = (0, import_react17.useState)("desktop");
18258
19441
  const [parentScrollSnap, setParentScrollSnap] = (0, import_react17.useState)(null);
@@ -18531,6 +19714,7 @@ function OhhwellsBridge() {
18531
19714
  hoveredItemElRef.current = null;
18532
19715
  setHoveredItemRect(null);
18533
19716
  setFloatingPanel(null);
19717
+ setFloatingPanelPos(null);
18534
19718
  setLogoSizeDraft(null);
18535
19719
  if (!activeElRef.current) {
18536
19720
  if (nestedGroup?.isConnected) {
@@ -19140,6 +20324,15 @@ function OhhwellsBridge() {
19140
20324
  }
19141
20325
  const clientX = e?.clientX ?? selected.getBoundingClientRect().left + 8;
19142
20326
  const clientY = e?.clientY ?? selected.getBoundingClientRect().top + 8;
20327
+ if (isCtaButton(selected) && collectionDragEnabled(selected)) {
20328
+ buttonCollectionDragRef.current = selected;
20329
+ if (e?.dataTransfer) {
20330
+ e.dataTransfer.effectAllowed = "move";
20331
+ e.dataTransfer.setData("text/plain", buttonId(selected) ?? "button");
20332
+ }
20333
+ setIsItemDragging(true);
20334
+ return;
20335
+ }
19143
20336
  if (startFooterLinkDrag(selected, clientX, clientY, true)) return;
19144
20337
  if (selected.hasAttribute("data-ohw-footer-col") || isInferredFooterGroup2(selected) && selected.closest("footer")) {
19145
20338
  if (startFooterColumnDrag(selected, clientX, clientY, true)) return;
@@ -19153,6 +20346,23 @@ function OhhwellsBridge() {
19153
20346
  );
19154
20347
  const handleItemDragEnd = (0, import_react17.useCallback)(
19155
20348
  (e) => {
20349
+ const collectionButton = buttonCollectionDragRef.current;
20350
+ if (collectionButton) {
20351
+ const x = e?.clientX;
20352
+ if (typeof x === "number" && x !== 0) reorderButtonInCollection(collectionButton, x);
20353
+ const collection = buttonCollectionOf(collectionButton);
20354
+ if (collection) {
20355
+ const persisted = persistCollectionOrder(collection, editContentRef.current);
20356
+ if (persisted) {
20357
+ editContentRef.current = persisted.content;
20358
+ postToParent2({ type: "ow:change", nodes: persisted.nodes });
20359
+ }
20360
+ }
20361
+ buttonCollectionDragRef.current = null;
20362
+ setIsItemDragging(false);
20363
+ if (collectionButton.isConnected) setToolbarRect(collectionButton.getBoundingClientRect());
20364
+ return;
20365
+ }
19156
20366
  if (footerDragRef.current) {
19157
20367
  const x = e?.clientX;
19158
20368
  const y = e?.clientY;
@@ -19175,7 +20385,7 @@ function OhhwellsBridge() {
19175
20385
  }
19176
20386
  setIsItemDragging(false);
19177
20387
  },
19178
- [commitFooterDrag, commitNavDrag, navDragRef]
20388
+ [commitFooterDrag, commitNavDrag, navDragRef, postToParent2]
19179
20389
  );
19180
20390
  const handleItemChromePointerDown = (0, import_react17.useCallback)((e) => {
19181
20391
  if (e.button !== 0) return;
@@ -19261,8 +20471,25 @@ function OhhwellsBridge() {
19261
20471
  setToolbarRect(anchor.getBoundingClientRect());
19262
20472
  setToolbarShowEditLink(false);
19263
20473
  setActiveCommands(/* @__PURE__ */ new Set());
19264
- setFloatingPanel(null);
19265
- setLogoSizeDraft(null);
20474
+ const panel = floatingPanelRef.current;
20475
+ if (panel?.kind === "button-style" && isCtaButton(anchor)) {
20476
+ const id = buttonId(anchor);
20477
+ if (id && panel.buttonId !== id) {
20478
+ captureButtonOrigin(anchor);
20479
+ setFloatingPanelPos(null);
20480
+ setFloatingPanel({
20481
+ ...panel,
20482
+ key: `button-style:${id}`,
20483
+ buttonId: id,
20484
+ context: buttonStyleContext(anchor)
20485
+ });
20486
+ setButtonStyleTick((n) => n + 1);
20487
+ }
20488
+ } else {
20489
+ setFloatingPanel(null);
20490
+ setFloatingPanelPos(null);
20491
+ setLogoSizeDraft(null);
20492
+ }
19266
20493
  }, [deactivate, markSelected]);
19267
20494
  const selectFrame = (0, import_react17.useCallback)((el) => {
19268
20495
  if (!isNavigationContainer(el)) return;
@@ -19302,6 +20529,7 @@ function OhhwellsBridge() {
19302
20529
  setToolbarShowEditLink(false);
19303
20530
  setActiveCommands(/* @__PURE__ */ new Set());
19304
20531
  setFloatingPanel(null);
20532
+ setFloatingPanelPos(null);
19305
20533
  setLogoSizeDraft(null);
19306
20534
  }, [deactivate, markSelected, postToParent2]);
19307
20535
  const selectLogo = (0, import_react17.useCallback)(
@@ -19356,6 +20584,87 @@ function OhhwellsBridge() {
19356
20584
  row
19357
20585
  });
19358
20586
  }, []);
20587
+ const rememberButtonTokens = (0, import_react17.useCallback)(
20588
+ (content, tokens, nodes) => {
20589
+ if (nodes.length === 0) return content;
20590
+ const next = { ...content };
20591
+ for (const node of nodes) next[node.key] = node.text;
20592
+ editContentRef.current = next;
20593
+ postToParent2({ type: "ow:change", nodes });
20594
+ return next;
20595
+ },
20596
+ [postToParent2]
20597
+ );
20598
+ const tokensForButton = (0, import_react17.useCallback)(
20599
+ (el, persistFallback = false) => {
20600
+ const stored = readStoredStyleTokens(editContentRef.current);
20601
+ if (stored) return stored;
20602
+ const ensured = ensureButtonStyleTokens(document, editContentRef.current);
20603
+ if (ensured.tokens) {
20604
+ rememberButtonTokens(editContentRef.current, ensured.tokens, ensured.nodes);
20605
+ return ensured.tokens;
20606
+ }
20607
+ const fallback = tokensFromButton(el);
20608
+ if (persistFallback) rememberButtonTokens(editContentRef.current, fallback, styleTokenNodes(fallback));
20609
+ return fallback;
20610
+ },
20611
+ [rememberButtonTokens]
20612
+ );
20613
+ const openButtonStylePanel = (0, import_react17.useCallback)(
20614
+ (anchor) => {
20615
+ const id = buttonId(anchor);
20616
+ if (!id) return;
20617
+ captureButtonOrigin(anchor);
20618
+ tokensForButton(anchor);
20619
+ setFloatingPanelPos(null);
20620
+ setParentScrollSnap(parentScrollRef.current);
20621
+ setFloatingPanel({
20622
+ key: `button-style:${id}`,
20623
+ title: "Style",
20624
+ context: buttonStyleContext(anchor),
20625
+ kind: "button-style",
20626
+ buttonId: id
20627
+ });
20628
+ },
20629
+ [tokensForButton]
20630
+ );
20631
+ const applySelectedButtonStyle = (0, import_react17.useCallback)(
20632
+ (patch) => {
20633
+ const panel = floatingPanelRef.current;
20634
+ const id = panel?.kind === "button-style" ? panel.buttonId : null;
20635
+ const el = id ? document.querySelector(`[data-ohw-href-key="${CSS.escape(id)}"]`) : null;
20636
+ if (!el || !id || !isCtaButton(el)) return;
20637
+ const tokens = tokensFromButton(el);
20638
+ const next = { ...assignmentFor(el, editContentRef.current, tokens), ...patch };
20639
+ const assignments = withAssignment(editContentRef.current, id, next);
20640
+ const text = JSON.stringify(assignments);
20641
+ editContentRef.current = { ...editContentRef.current, [BUTTON_ASSIGNMENTS_KEY]: text };
20642
+ applyButtonStyle(el, next, tokens);
20643
+ postToParent2({ type: "ow:change", nodes: [{ key: BUTTON_ASSIGNMENTS_KEY, text }] });
20644
+ setButtonStyleTick((n) => n + 1);
20645
+ if (selectedElRef.current === el) setToolbarRect(el.getBoundingClientRect());
20646
+ },
20647
+ [postToParent2]
20648
+ );
20649
+ (0, import_react17.useEffect)(() => {
20650
+ const onDragOver = (e) => {
20651
+ const dragged = buttonCollectionDragRef.current;
20652
+ if (!dragged) return;
20653
+ e.preventDefault();
20654
+ if (e.dataTransfer) e.dataTransfer.dropEffect = "move";
20655
+ reorderButtonInCollection(dragged, e.clientX);
20656
+ };
20657
+ const onDrop = (e) => {
20658
+ if (!buttonCollectionDragRef.current) return;
20659
+ e.preventDefault();
20660
+ };
20661
+ document.addEventListener("dragover", onDragOver);
20662
+ document.addEventListener("drop", onDrop);
20663
+ return () => {
20664
+ document.removeEventListener("dragover", onDragOver);
20665
+ document.removeEventListener("drop", onDrop);
20666
+ };
20667
+ }, []);
19359
20668
  const isEditModeRef = (0, import_react17.useRef)(false);
19360
20669
  const requestMissingSocialIconsRef = (0, import_react17.useRef)(() => {
19361
20670
  });
@@ -19398,11 +20707,13 @@ function OhhwellsBridge() {
19398
20707
  );
19399
20708
  const closeFloatingPanelOnly = (0, import_react17.useCallback)(() => {
19400
20709
  setFloatingPanel(null);
20710
+ setFloatingPanelPos(null);
19401
20711
  setLogoSizeDraft(null);
19402
20712
  }, []);
19403
20713
  closeFloatingPanelOnlyRef.current = closeFloatingPanelOnly;
19404
20714
  const closeFloatingPanelAndDeselect = (0, import_react17.useCallback)(() => {
19405
20715
  setFloatingPanel(null);
20716
+ setFloatingPanelPos(null);
19406
20717
  setLogoSizeDraft(null);
19407
20718
  deselectRef.current();
19408
20719
  }, []);
@@ -19670,6 +20981,7 @@ function OhhwellsBridge() {
19670
20981
  reconcileSocialsFromContent(content);
19671
20982
  applySocialsDisplayFromContent(content);
19672
20983
  applySocialsLabelsFromContent(content, document, { fillEmptyOnly: isEditModeRef.current });
20984
+ syncButtonsFromContent(document, content);
19673
20985
  if (isEditModeRef.current) requestMissingSocialIconsRef.current();
19674
20986
  if (typeof content[STYLE_STORE_KEY] === "string") {
19675
20987
  applyStylesToDom(parseStyleStore(content[STYLE_STORE_KEY]));
@@ -19873,6 +21185,7 @@ function OhhwellsBridge() {
19873
21185
  reconcileSocialsFromContent(content);
19874
21186
  applySocialsDisplayFromContent(content);
19875
21187
  applySocialsLabelsFromContent(content, document, { fillEmptyOnly: isEditModeRef.current });
21188
+ syncButtonsFromContent(document, content);
19876
21189
  if (isEditModeRef.current) requestMissingSocialIconsRef.current();
19877
21190
  if (typeof content[STYLE_STORE_KEY] === "string") {
19878
21191
  applyStylesToDom(parseStyleStore(content[STYLE_STORE_KEY]));
@@ -19972,7 +21285,10 @@ function OhhwellsBridge() {
19972
21285
  if (roots.length === 0) {
19973
21286
  reconcileNavbarItemsFromContent(contentForNav());
19974
21287
  reconcileFooterOrderFromContent(contentForNav());
19975
- if (isEditMode) syncNavigationDragCursorAttrs();
21288
+ if (isEditMode) {
21289
+ syncButtonsFromContent(document, contentForNav());
21290
+ syncNavigationDragCursorAttrs();
21291
+ }
19976
21292
  return;
19977
21293
  }
19978
21294
  let rafId = null;
@@ -19984,7 +21300,7 @@ function OhhwellsBridge() {
19984
21300
  }
19985
21301
  };
19986
21302
  const run = () => {
19987
- if (footerDragRef.current || navDragRef.current || applying) return;
21303
+ if (footerDragRef.current || navDragRef.current || buttonCollectionDragRef.current || applying) return;
19988
21304
  applying = true;
19989
21305
  observer?.disconnect();
19990
21306
  try {
@@ -19994,6 +21310,7 @@ function OhhwellsBridge() {
19994
21310
  reconcileSocialsFromContent(content);
19995
21311
  applySocialsDisplayFromContent(content);
19996
21312
  applySocialsLabelsFromContent(content, document, { fillEmptyOnly: isEditModeRef.current });
21313
+ syncButtonsFromContent(document, content);
19997
21314
  if (isEditModeRef.current) requestMissingSocialIconsRef.current();
19998
21315
  document.querySelectorAll("footer [data-ohw-href-key]").forEach((el) => {
19999
21316
  if (isFooterHrefKey(el.getAttribute("data-ohw-href-key")) || getSocialItem(el)) {
@@ -20028,6 +21345,44 @@ function OhhwellsBridge() {
20028
21345
  observer?.disconnect();
20029
21346
  };
20030
21347
  }, [isEditMode, pathname, subdomain, fetchState, resyncSelectedNavigationItem]);
21348
+ (0, import_react17.useEffect)(() => {
21349
+ if (!isEditMode) return;
21350
+ let applying = false;
21351
+ let rafId = null;
21352
+ const run = () => {
21353
+ if (applying || buttonCollectionDragRef.current) return;
21354
+ const content = editContentRef.current;
21355
+ if (!content[BUTTON_COLLECTIONS_KEY] && !content[BUTTON_SNAPSHOTS_KEY]) return;
21356
+ applying = true;
21357
+ try {
21358
+ syncButtonsFromContent(document, content);
21359
+ } finally {
21360
+ applying = false;
21361
+ }
21362
+ };
21363
+ const schedule = () => {
21364
+ if (rafId != null) return;
21365
+ rafId = requestAnimationFrame(() => {
21366
+ rafId = null;
21367
+ run();
21368
+ });
21369
+ };
21370
+ const observer = new MutationObserver((mutations) => {
21371
+ if (mutations.every((m) => {
21372
+ const t = m.target;
21373
+ return t instanceof Element && Boolean(t.closest("[data-ohw-bridge], [data-ohw-bridge-root], [data-ohw-button-collection]"));
21374
+ })) {
21375
+ return;
21376
+ }
21377
+ schedule();
21378
+ });
21379
+ observer.observe(document.body, { childList: true, subtree: true });
21380
+ run();
21381
+ return () => {
21382
+ if (rafId != null) cancelAnimationFrame(rafId);
21383
+ observer.disconnect();
21384
+ };
21385
+ }, [isEditMode, pathname]);
20031
21386
  (0, import_react17.useEffect)(() => {
20032
21387
  if (!isEditMode) return;
20033
21388
  let lastPosted = 0;
@@ -21997,6 +23352,7 @@ function OhhwellsBridge() {
21997
23352
  editContentRef.current = { ...editContentRef.current, ...content };
21998
23353
  reconcileNavbarItemsFromContent(editContentRef.current);
21999
23354
  reconcileFooterOrderFromContent(editContentRef.current);
23355
+ syncButtonsFromContent(document, editContentRef.current);
22000
23356
  syncNavigationDragCursorAttrs();
22001
23357
  if (typeof content[STYLE_STORE_KEY] === "string") {
22002
23358
  applyStylesToDom(parseStyleStore(content[STYLE_STORE_KEY]));
@@ -23411,12 +24767,12 @@ function OhhwellsBridge() {
23411
24767
  return;
23412
24768
  }
23413
24769
  if (type !== "ow:logo-size-set") return;
23414
- const px = Number(e.data.px);
23415
- if (!Number.isFinite(px)) return;
23416
- const next = editorViewport === "mobile" ? { ...logoSizeDraft, mobilePx: px, mobileFollowing: false } : {
24770
+ const px2 = Number(e.data.px);
24771
+ if (!Number.isFinite(px2)) return;
24772
+ const next = editorViewport === "mobile" ? { ...logoSizeDraft, mobilePx: px2, mobileFollowing: false } : {
23417
24773
  ...logoSizeDraft,
23418
- desktopPx: px,
23419
- mobilePx: logoSizeDraft.mobileFollowing ? px : logoSizeDraft.mobilePx
24774
+ desktopPx: px2,
24775
+ mobilePx: logoSizeDraft.mobileFollowing ? px2 : logoSizeDraft.mobilePx
23420
24776
  };
23421
24777
  setLogoSizeDraft(next);
23422
24778
  persistLogoSizeDraft(session.placement, next);
@@ -23514,6 +24870,36 @@ function OhhwellsBridge() {
23514
24870
  const handleDuplicateSelected = (0, import_react17.useCallback)(() => {
23515
24871
  const selected = selectedElRef.current;
23516
24872
  if (!selected || !isNavigationItem2(selected)) return;
24873
+ if (isCtaButton(selected)) {
24874
+ const id = buttonId(selected);
24875
+ if (!id) return;
24876
+ const tokens = tokensForButton(selected, true);
24877
+ if (!readAssignments(editContentRef.current)[id]) {
24878
+ const assignment = assignmentFor(selected, editContentRef.current, tokens);
24879
+ const assignments = withAssignment(editContentRef.current, id, assignment);
24880
+ editContentRef.current = {
24881
+ ...editContentRef.current,
24882
+ [BUTTON_ASSIGNMENTS_KEY]: JSON.stringify(assignments)
24883
+ };
24884
+ applyButtonStyle(selected, assignment, tokens);
24885
+ }
24886
+ const result = duplicateButton(selected, editContentRef.current);
24887
+ if (!result) return;
24888
+ editContentRef.current = result.content;
24889
+ const copyHref = result.copy.getAttribute("data-ohw-href-key");
24890
+ const copyHrefVal = copyHref ? result.content[copyHref] : void 0;
24891
+ if (copyHref && copyHrefVal !== void 0) applyLinkByKey(copyHref, copyHrefVal);
24892
+ postToParent2({ type: "ow:change", nodes: result.nodes });
24893
+ enforceLinkHrefs();
24894
+ requestAnimationFrame(() => {
24895
+ selectRef.current(result.copy);
24896
+ requestAnimationFrame(() => {
24897
+ const el = selectedElRef.current;
24898
+ if (el?.isConnected) setToolbarRect(el.getBoundingClientRect());
24899
+ });
24900
+ });
24901
+ return;
24902
+ }
23517
24903
  const hrefKey = selected.getAttribute("data-ohw-href-key");
23518
24904
  if (!hrefKey) return;
23519
24905
  const social = getSocialItem(selected);
@@ -23643,7 +25029,7 @@ function OhhwellsBridge() {
23643
25029
  selectRef.current(result.anchor);
23644
25030
  });
23645
25031
  }
23646
- }, [postToParent2]);
25032
+ }, [postToParent2, tokensForButton]);
23647
25033
  const runPendingDeleteUndo = (0, import_react17.useCallback)(() => {
23648
25034
  const pending = pendingDeleteUndoRef.current;
23649
25035
  if (!pending) return false;
@@ -23655,6 +25041,38 @@ function OhhwellsBridge() {
23655
25041
  const handleDeleteSelected = (0, import_react17.useCallback)(() => {
23656
25042
  const selected = selectedElRef.current;
23657
25043
  if (!selected) return false;
25044
+ if (isCtaButton(selected)) {
25045
+ if (!canDeleteButton(selected)) return false;
25046
+ const previousContent = editContentRef.current;
25047
+ const result = deleteButton(selected, previousContent);
25048
+ if (!result) return false;
25049
+ editContentRef.current = result.content;
25050
+ postToParent2({ type: "ow:change", nodes: result.nodes });
25051
+ const actionId = typeof crypto !== "undefined" && "randomUUID" in crypto ? crypto.randomUUID() : `delete-${Date.now()}`;
25052
+ const restoreNodes = result.nodes.map((node) => ({
25053
+ key: node.key,
25054
+ text: previousContent[node.key] ?? ""
25055
+ }));
25056
+ pendingDeleteUndoRef.current = {
25057
+ actionId,
25058
+ restore: () => {
25059
+ result.undo();
25060
+ editContentRef.current = { ...editContentRef.current, ...Object.fromEntries(restoreNodes.map((node) => [node.key, node.text])) };
25061
+ postToParent2({ type: "ow:change", nodes: restoreNodes });
25062
+ syncButtonsFromContent(document, editContentRef.current);
25063
+ }
25064
+ };
25065
+ deselectRef.current();
25066
+ postToParent2({
25067
+ type: "ow:toast",
25068
+ title: "Button deleted",
25069
+ toastType: "success",
25070
+ actionLabel: "Undo",
25071
+ actionId,
25072
+ duration: 6e3
25073
+ });
25074
+ return true;
25075
+ }
23658
25076
  return deleteSelectedNavFooterItem({
23659
25077
  selected,
23660
25078
  isTextEditing: Boolean(activeElRef.current),
@@ -23792,14 +25210,14 @@ function OhhwellsBridge() {
23792
25210
  },
23793
25211
  [postToParent2]
23794
25212
  );
23795
- return /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)(import_jsx_runtime33.Fragment, { children: [
23796
- /* @__PURE__ */ (0, import_jsx_runtime33.jsx)("div", { id: "ohw-loader", suppressHydrationWarning: true, style: { ...OHW_LOADER_STYLE, display: "none" }, children: /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(OhwLoaderSpinner, {}) }),
23797
- /* @__PURE__ */ (0, import_jsx_runtime33.jsx)("script", { suppressHydrationWarning: true, dangerouslySetInnerHTML: { __html: OHW_LOADER_PREHYDRATE_SCRIPT } }),
23798
- subdomain && !isEditMode && showBranding && /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(MadeWithOhhWells, {}),
25213
+ return /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)(import_jsx_runtime34.Fragment, { children: [
25214
+ /* @__PURE__ */ (0, import_jsx_runtime34.jsx)("div", { id: "ohw-loader", suppressHydrationWarning: true, style: { ...OHW_LOADER_STYLE, display: "none" }, children: /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(OhwLoaderSpinner, {}) }),
25215
+ /* @__PURE__ */ (0, import_jsx_runtime34.jsx)("script", { suppressHydrationWarning: true, dangerouslySetInnerHTML: { __html: OHW_LOADER_PREHYDRATE_SCRIPT } }),
25216
+ subdomain && !isEditMode && showBranding && /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(MadeWithOhhWells, {}),
23799
25217
  bridgeRoot ? (0, import_react_dom5.createPortal)(
23800
- /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)(import_jsx_runtime33.Fragment, { children: [
23801
- /* @__PURE__ */ (0, import_jsx_runtime33.jsx)("div", { ref: attachVisibleViewport, "data-ohw-visible-viewport": "", "aria-hidden": true }),
23802
- isEditMode && /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
25218
+ /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)(import_jsx_runtime34.Fragment, { children: [
25219
+ /* @__PURE__ */ (0, import_jsx_runtime34.jsx)("div", { ref: attachVisibleViewport, "data-ohw-visible-viewport": "", "aria-hidden": true }),
25220
+ isEditMode && /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
23803
25221
  AiSectionOverlay,
23804
25222
  {
23805
25223
  postToParent: postToParent2,
@@ -23807,12 +25225,12 @@ function OhhwellsBridge() {
23807
25225
  onSelectionChange: handleAiSectionSelectionChange
23808
25226
  }
23809
25227
  ),
23810
- isSectionDragging && sectionDropSlots.map((slot, i) => /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
25228
+ isSectionDragging && sectionDropSlots.map((slot, i) => /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
23811
25229
  "div",
23812
25230
  {
23813
25231
  className: "pointer-events-none fixed z-2147483646",
23814
25232
  style: { left: slot.left, top: slot.y, width: slot.width, height: 3, transform: "translateY(-50%)" },
23815
- children: /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
25233
+ children: /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
23816
25234
  DropIndicator,
23817
25235
  {
23818
25236
  direction: "horizontal",
@@ -23823,7 +25241,7 @@ function OhhwellsBridge() {
23823
25241
  },
23824
25242
  `section-drop-${slot.insertIndex}-${i}`
23825
25243
  )),
23826
- Object.entries(uploadingRects).map(([key, { rect, fadingOut }]) => /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
25244
+ Object.entries(uploadingRects).map(([key, { rect, fadingOut }]) => /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
23827
25245
  MediaOverlay,
23828
25246
  {
23829
25247
  hover: { key, rect, elementType: "image", isDragOver: false, hasTextOverlap: false },
@@ -23834,7 +25252,7 @@ function OhhwellsBridge() {
23834
25252
  },
23835
25253
  `uploading-${key}`
23836
25254
  )),
23837
- mediaHover && !(mediaHover.key in uploadingRects) && mediaHover.key !== selectedMedia?.key && /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
25255
+ mediaHover && !(mediaHover.key in uploadingRects) && mediaHover.key !== selectedMedia?.key && /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
23838
25256
  MediaOverlay,
23839
25257
  {
23840
25258
  hover: mediaHover,
@@ -23845,7 +25263,7 @@ function OhhwellsBridge() {
23845
25263
  onVideoSettingsChange: handleVideoSettingsChange
23846
25264
  }
23847
25265
  ),
23848
- selectedMedia && !(selectedMedia.key in uploadingRects) && !linkPopover && /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
25266
+ selectedMedia && !(selectedMedia.key in uploadingRects) && !linkPopover && /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
23849
25267
  MediaOverlay,
23850
25268
  {
23851
25269
  hover: selectedMedia,
@@ -23857,7 +25275,7 @@ function OhhwellsBridge() {
23857
25275
  onVideoSettingsChange: handleVideoSettingsChange
23858
25276
  }
23859
25277
  ),
23860
- carouselHover && !linkPopover && !isItemDragging && /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
25278
+ carouselHover && !linkPopover && !isItemDragging && /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
23861
25279
  CarouselOverlay,
23862
25280
  {
23863
25281
  hover: carouselHover,
@@ -23865,10 +25283,10 @@ function OhhwellsBridge() {
23865
25283
  cueOnly: !!carouselHover.fullBleedSectionId && carouselHover.fullBleedSectionId !== selectedAiSectionId
23866
25284
  }
23867
25285
  ),
23868
- siblingHintRect && !linkPopover && !isItemDragging && siblingHintRects.length === 0 && /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(ItemInteractionLayer, { rect: siblingHintRect, state: "sibling-hint" }),
23869
- siblingHintRects.length > 0 && !linkPopover && !isItemDragging && siblingHintRects.map((rect, i) => /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(ItemInteractionLayer, { rect, state: "sibling-hint" }, `sibling-hint-${i}`)),
23870
- isItemDragging && draggedItemRect && selectedElRef.current !== footerDragRef.current?.draggedEl && selectedElRef.current !== navDragRef.current?.draggedEl && /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(ItemInteractionLayer, { rect: draggedItemRect, state: "dragging" }),
23871
- isItemDragging && footerDropSlots.map((slot, i) => /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
25286
+ siblingHintRect && !linkPopover && !isItemDragging && siblingHintRects.length === 0 && /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(ItemInteractionLayer, { rect: siblingHintRect, state: "sibling-hint" }),
25287
+ siblingHintRects.length > 0 && !linkPopover && !isItemDragging && siblingHintRects.map((rect, i) => /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(ItemInteractionLayer, { rect, state: "sibling-hint" }, `sibling-hint-${i}`)),
25288
+ isItemDragging && draggedItemRect && selectedElRef.current !== footerDragRef.current?.draggedEl && selectedElRef.current !== navDragRef.current?.draggedEl && /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(ItemInteractionLayer, { rect: draggedItemRect, state: "dragging" }),
25289
+ isItemDragging && footerDropSlots.map((slot, i) => /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
23872
25290
  "div",
23873
25291
  {
23874
25292
  className: "pointer-events-none fixed z-2147483646",
@@ -23878,7 +25296,7 @@ function OhhwellsBridge() {
23878
25296
  width: slot.width,
23879
25297
  height: slot.height
23880
25298
  },
23881
- children: /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
25299
+ children: /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
23882
25300
  DropIndicator,
23883
25301
  {
23884
25302
  direction: slot.direction,
@@ -23889,7 +25307,7 @@ function OhhwellsBridge() {
23889
25307
  },
23890
25308
  `footer-drop-${slot.direction}-${slot.columnIndex}-${slot.insertIndex}-${i}`
23891
25309
  )),
23892
- isItemDragging && navDropSlots.map((slot, i) => /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
25310
+ isItemDragging && navDropSlots.map((slot, i) => /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
23893
25311
  "div",
23894
25312
  {
23895
25313
  className: "pointer-events-none fixed z-2147483646",
@@ -23899,7 +25317,7 @@ function OhhwellsBridge() {
23899
25317
  width: slot.width,
23900
25318
  height: slot.height
23901
25319
  },
23902
- children: /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
25320
+ children: /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
23903
25321
  DropIndicator,
23904
25322
  {
23905
25323
  direction: slot.direction,
@@ -23910,10 +25328,10 @@ function OhhwellsBridge() {
23910
25328
  },
23911
25329
  `nav-drop-${slot.direction}-${slot.parentId ?? "root"}-${slot.insertIndex}-${i}`
23912
25330
  )),
23913
- hoveredNavContainerRect && (toolbarVariant !== "select-frame" || isFooterFrameSelection) && !linkPopover && !isItemDragging && /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(ItemInteractionLayer, { rect: hoveredNavContainerRect, state: "hover" }),
23914
- hoveredItemRect && !linkPopover && !hoveredNavContainerRect && !isItemDragging && hoveredItemElRef.current !== selectedElRef.current && /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(ItemInteractionLayer, { rect: hoveredItemRect, state: "hover" }),
23915
- hoveredTextRect && !hoveredNavContainerRect && !hoveredItemRect && !isItemDragging && toolbarVariant !== "rich-text" && /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(ItemInteractionLayer, { rect: hoveredTextRect, state: "hover" }),
23916
- formPickRect && !isItemDragging && /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
25331
+ hoveredNavContainerRect && (toolbarVariant !== "select-frame" || isFooterFrameSelection) && !linkPopover && !isItemDragging && /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(ItemInteractionLayer, { rect: hoveredNavContainerRect, state: "hover" }),
25332
+ hoveredItemRect && !linkPopover && !hoveredNavContainerRect && !isItemDragging && hoveredItemElRef.current !== selectedElRef.current && /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(ItemInteractionLayer, { rect: hoveredItemRect, state: "hover" }),
25333
+ hoveredTextRect && !hoveredNavContainerRect && !hoveredItemRect && !isItemDragging && toolbarVariant !== "rich-text" && /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(ItemInteractionLayer, { rect: hoveredTextRect, state: "hover" }),
25334
+ formPickRect && !isItemDragging && /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
23917
25335
  ItemInteractionLayer,
23918
25336
  {
23919
25337
  rect: formPickRect,
@@ -23921,13 +25339,13 @@ function OhhwellsBridge() {
23921
25339
  itemDragSurface: false,
23922
25340
  toolbarAlign: "left",
23923
25341
  chromeGap: 24,
23924
- toolbar: fieldPickRect ? void 0 : /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)(
25342
+ toolbar: fieldPickRect ? void 0 : /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)(
23925
25343
  "div",
23926
25344
  {
23927
25345
  "data-ohw-form-toolbar": "",
23928
25346
  className: "pointer-events-auto flex items-center gap-0.5 whitespace-nowrap rounded-lg border border-border bg-background p-1 shadow-md",
23929
25347
  children: [
23930
- /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
25348
+ /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
23931
25349
  "button",
23932
25350
  {
23933
25351
  type: "button",
@@ -23935,11 +25353,11 @@ function OhhwellsBridge() {
23935
25353
  className: "flex h-7 w-7 items-center justify-center rounded-md text-foreground transition-colors hover:bg-muted/80",
23936
25354
  onClick: () => setFieldTypePickerOpen((open) => !open),
23937
25355
  "data-ohw-add-field": "",
23938
- children: /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(import_lucide_react17.Plus, { size: 15, "aria-hidden": true })
25356
+ children: /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(import_lucide_react18.Plus, { size: 15, "aria-hidden": true })
23939
25357
  }
23940
25358
  ),
23941
- /* @__PURE__ */ (0, import_jsx_runtime33.jsx)("div", { className: "mx-0.5 h-5 w-px bg-border" }),
23942
- /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)(
25359
+ /* @__PURE__ */ (0, import_jsx_runtime34.jsx)("div", { className: "mx-0.5 h-5 w-px bg-border" }),
25360
+ /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)(
23943
25361
  "button",
23944
25362
  {
23945
25363
  type: "button",
@@ -23955,11 +25373,11 @@ function OhhwellsBridge() {
23955
25373
  });
23956
25374
  },
23957
25375
  children: [
23958
- /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(import_lucide_react17.Settings, { size: 14, "aria-hidden": true }),
25376
+ /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(import_lucide_react18.Settings, { size: 14, "aria-hidden": true }),
23959
25377
  "Form settings",
23960
25378
  formPickCount ? (
23961
25379
  // Counter pill, per the design — not a text suffix.
23962
- /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
25380
+ /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
23963
25381
  "span",
23964
25382
  {
23965
25383
  "data-ohw-form-count": "",
@@ -23971,8 +25389,8 @@ function OhhwellsBridge() {
23971
25389
  ]
23972
25390
  }
23973
25391
  ),
23974
- /* @__PURE__ */ (0, import_jsx_runtime33.jsx)("div", { className: "mx-0.5 h-5 w-px bg-border" }),
23975
- /* @__PURE__ */ (0, import_jsx_runtime33.jsx)("div", { className: "flex items-center rounded-md bg-muted/70 p-0.5", children: ["default", "success"].map((state) => /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
25392
+ /* @__PURE__ */ (0, import_jsx_runtime34.jsx)("div", { className: "mx-0.5 h-5 w-px bg-border" }),
25393
+ /* @__PURE__ */ (0, import_jsx_runtime34.jsx)("div", { className: "flex items-center rounded-md bg-muted/70 p-0.5", children: ["default", "success"].map((state) => /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
23976
25394
  "button",
23977
25395
  {
23978
25396
  type: "button",
@@ -24003,7 +25421,7 @@ function OhhwellsBridge() {
24003
25421
  )
24004
25422
  }
24005
25423
  ),
24006
- formHoverRect && !isItemDragging && /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
25424
+ formHoverRect && !isItemDragging && /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
24007
25425
  ItemInteractionLayer,
24008
25426
  {
24009
25427
  rect: formHoverRect,
@@ -24011,7 +25429,7 @@ function OhhwellsBridge() {
24011
25429
  chromeGap: formHoverElRef.current && getFieldWrapper(formHoverElRef.current) ? 8 : 24
24012
25430
  }
24013
25431
  ),
24014
- fieldPickRect && fieldPickState && !isItemDragging && toolbarVariant !== "rich-text" && /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
25432
+ fieldPickRect && fieldPickState && !isItemDragging && toolbarVariant !== "rich-text" && /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
24015
25433
  ItemInteractionLayer,
24016
25434
  {
24017
25435
  rect: fieldPickRect,
@@ -24023,7 +25441,7 @@ function OhhwellsBridge() {
24023
25441
  dragHandleLabel: "Reorder field",
24024
25442
  onDragHandleDragStart: handleFieldDragStart,
24025
25443
  onDragHandleDragEnd: handleFieldDragEnd,
24026
- toolbar: /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
25444
+ toolbar: /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
24027
25445
  FormFieldToolbar,
24028
25446
  {
24029
25447
  type: fieldPickState.type,
@@ -24036,12 +25454,12 @@ function OhhwellsBridge() {
24036
25454
  )
24037
25455
  }
24038
25456
  ),
24039
- fieldDragging ? fieldDropSlots.map((slot, i) => /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
25457
+ fieldDragging ? fieldDropSlots.map((slot, i) => /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
24040
25458
  "div",
24041
25459
  {
24042
25460
  className: "pointer-events-none fixed z-[2147483644]",
24043
25461
  style: { top: slot.top, left: slot.left, width: slot.width },
24044
- children: /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
25462
+ children: /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
24045
25463
  DropIndicator,
24046
25464
  {
24047
25465
  direction: "horizontal",
@@ -24054,7 +25472,7 @@ function OhhwellsBridge() {
24054
25472
  )) : null,
24055
25473
  fieldTypePickerOpen && formPickRect ? (() => {
24056
25474
  const toolbar = document.querySelector("[data-ohw-form-toolbar]")?.getBoundingClientRect();
24057
- return /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
25475
+ return /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
24058
25476
  "div",
24059
25477
  {
24060
25478
  className: "pointer-events-none fixed z-[2147483645]",
@@ -24062,12 +25480,12 @@ function OhhwellsBridge() {
24062
25480
  top: toolbar ? toolbar.bottom + 6 : formPickRect.top + 16,
24063
25481
  left: toolbar ? toolbar.left : formPickRect.left + 24
24064
25482
  },
24065
- children: /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(FieldTypePicker, { onPick: handleAddField })
25483
+ children: /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(FieldTypePicker, { onPick: handleAddField })
24066
25484
  }
24067
25485
  );
24068
25486
  })() : null,
24069
- toolbarVariant === "select-frame" && toolbarRect && !linkPopover && !isItemDragging && !isFooterFrameSelection && selectedElRef.current && isNavbarLinksContainer2(selectedElRef.current) && /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(NavbarContainerChrome, { rect: toolbarRect, onAdd: handleAddTopLevelNavItem }),
24070
- toolbarVariant === "select-frame" && toolbarRect && !linkPopover && !isItemDragging && !isFooterFrameSelection && selectedElRef.current && isFooterLinksContainer(selectedElRef.current) && /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
25487
+ toolbarVariant === "select-frame" && toolbarRect && !linkPopover && !isItemDragging && !isFooterFrameSelection && selectedElRef.current && isNavbarLinksContainer2(selectedElRef.current) && /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(NavbarContainerChrome, { rect: toolbarRect, onAdd: handleAddTopLevelNavItem }),
25488
+ toolbarVariant === "select-frame" && toolbarRect && !linkPopover && !isItemDragging && !isFooterFrameSelection && selectedElRef.current && isFooterLinksContainer(selectedElRef.current) && /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
24071
25489
  FooterContainerChrome,
24072
25490
  {
24073
25491
  rect: toolbarRect,
@@ -24075,7 +25493,7 @@ function OhhwellsBridge() {
24075
25493
  addDisabled: !canAddFooterColumn()
24076
25494
  }
24077
25495
  ),
24078
- toolbarRect && !linkPopover && (toolbarVariant === "link-action" || toolbarVariant === "select-frame" || toolbarVariant === "logo") && /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
25496
+ toolbarRect && !linkPopover && (toolbarVariant === "link-action" || toolbarVariant === "select-frame" || toolbarVariant === "logo") && /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
24079
25497
  ItemInteractionLayer,
24080
25498
  {
24081
25499
  rect: isItemDragging && draggedItemRect && (footerDragRef.current?.wasSelected || navDragRef.current?.wasSelected) ? draggedItemRect : toolbarRect,
@@ -24091,18 +25509,25 @@ function OhhwellsBridge() {
24091
25509
  onItemPointerDown: toolbarVariant === "logo" ? void 0 : handleItemChromePointerDown,
24092
25510
  onItemClick: toolbarVariant === "logo" ? void 0 : handleItemChromeClick,
24093
25511
  itemDragSurface: toolbarVariant !== "logo" && !isFooterFrameSelection && !selectedIsSocialsRow,
24094
- toolbar: toolbarVariant === "link-action" && !isItemDragging || toolbarVariant === "select-frame" && (isFooterFrameSelection || selectedIsSocialsRow) && !isItemDragging ? /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
25512
+ toolbar: toolbarVariant === "link-action" && !isItemDragging || toolbarVariant === "select-frame" && (isFooterFrameSelection || selectedIsSocialsRow) && !isItemDragging ? /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
24095
25513
  ItemActionToolbar,
24096
25514
  {
24097
25515
  onEditLink: openLinkPopoverForSelected,
24098
25516
  onStyle: () => {
24099
25517
  const row = selectedElRef.current;
24100
25518
  if (!row) return;
24101
- if (floatingPanel?.kind === "socials-display") closeFloatingPanelOnly();
25519
+ suppressNextClickRef.current = true;
25520
+ suppressClickUntilRef.current = Date.now() + 500;
25521
+ if (isCtaButton(row)) {
25522
+ if (floatingPanelRef.current?.kind === "button-style") closeFloatingPanelOnly();
25523
+ else openButtonStylePanel(row);
25524
+ return;
25525
+ }
25526
+ if (floatingPanelRef.current?.kind === "socials-display") closeFloatingPanelOnly();
24102
25527
  else openSocialsDisplayPanel(row);
24103
25528
  },
24104
- showStyle: selectedIsSocialsRow,
24105
- styleActive: floatingPanel?.kind === "socials-display",
25529
+ showStyle: selectedIsSocialsRow || selectedIsCta,
25530
+ styleActive: floatingPanel?.kind === "socials-display" || floatingPanel?.kind === "button-style",
24106
25531
  onAddItem: handleAddChildItem,
24107
25532
  onSelectParent: handleSelectParent,
24108
25533
  onDuplicate: handleDuplicateSelected,
@@ -24113,7 +25538,7 @@ function OhhwellsBridge() {
24113
25538
  })(),
24114
25539
  editLinkDisabled: false,
24115
25540
  moreDisabled: false,
24116
- deleteDisabled: selectedElRef.current !== null && (() => {
25541
+ deleteDisabled: selectedElRef.current !== null && isCtaButton(selectedElRef.current) && !canDeleteButton(selectedElRef.current) || selectedElRef.current !== null && (() => {
24117
25542
  const social = getSocialItem(selectedElRef.current);
24118
25543
  return social ? !canRemoveSocialItem(social) : false;
24119
25544
  })(),
@@ -24126,7 +25551,7 @@ function OhhwellsBridge() {
24126
25551
  showAddItem: isFooterFrameSelection || selectedIsSocialsRow || !selectedIsCta && Boolean(
24127
25552
  selectedElRef.current && isNavbarHrefKey(selectedElRef.current.getAttribute("data-ohw-href-key")) && !isNestedNavChild(selectedElRef.current)
24128
25553
  ),
24129
- showMore: (!selectedIsCta || isFooterFrameSelection) && !selectedIsSocialsRow,
25554
+ showMore: !selectedIsSocialsRow,
24130
25555
  dropdownOpen: navDropdownPreviewOpen,
24131
25556
  onDropdownOpenChange: handleNavDropdownOpenChange,
24132
25557
  headingVisible: footerHeadingVisible,
@@ -24135,8 +25560,8 @@ function OhhwellsBridge() {
24135
25560
  ) : void 0
24136
25561
  }
24137
25562
  ),
24138
- toolbarRect && toolbarVariant === "rich-text" && !linkPopover && !isRectOutsideClip(toolbarRect, getIframeVisibleClip(parentScrollRef.current)) && /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)(import_jsx_runtime33.Fragment, { children: [
24139
- /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
25563
+ toolbarRect && toolbarVariant === "rich-text" && !linkPopover && !isRectOutsideClip(toolbarRect, getIframeVisibleClip(parentScrollRef.current)) && /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)(import_jsx_runtime34.Fragment, { children: [
25564
+ /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
24140
25565
  EditGlowChrome,
24141
25566
  {
24142
25567
  rect: toolbarRect,
@@ -24146,7 +25571,7 @@ function OhhwellsBridge() {
24146
25571
  hideHandle: isItemDragging
24147
25572
  }
24148
25573
  ),
24149
- /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
25574
+ /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
24150
25575
  FloatingToolbar,
24151
25576
  {
24152
25577
  rect: toolbarRect,
@@ -24159,7 +25584,7 @@ function OhhwellsBridge() {
24159
25584
  }
24160
25585
  )
24161
25586
  ] }),
24162
- maxBadge && /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)(
25587
+ maxBadge && /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)(
24163
25588
  "div",
24164
25589
  {
24165
25590
  "data-ohw-max-badge": "",
@@ -24185,7 +25610,7 @@ function OhhwellsBridge() {
24185
25610
  ]
24186
25611
  }
24187
25612
  ),
24188
- toggleState && !linkPopover && /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
25613
+ toggleState && !linkPopover && /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
24189
25614
  StateToggle,
24190
25615
  {
24191
25616
  rect: toggleState.rect,
@@ -24194,15 +25619,15 @@ function OhhwellsBridge() {
24194
25619
  onStateChange: handleStateChange
24195
25620
  }
24196
25621
  ),
24197
- sectionGap && !linkPopover && /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)(
25622
+ sectionGap && !linkPopover && /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)(
24198
25623
  "div",
24199
25624
  {
24200
25625
  "data-ohw-section-insert-line": "",
24201
25626
  className: "fixed left-0 w-full z-2147483646 flex items-center pointer-events-none",
24202
25627
  style: { top: sectionGap.y, transform: "translateY(-50%)" },
24203
25628
  children: [
24204
- /* @__PURE__ */ (0, import_jsx_runtime33.jsx)("div", { className: "flex-1 bg-bridge-primary", style: { height: 3 } }),
24205
- /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
25629
+ /* @__PURE__ */ (0, import_jsx_runtime34.jsx)("div", { className: "flex-1 bg-bridge-primary", style: { height: 3 } }),
25630
+ /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
24206
25631
  Badge,
24207
25632
  {
24208
25633
  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",
@@ -24219,11 +25644,11 @@ function OhhwellsBridge() {
24219
25644
  children: "Add Section"
24220
25645
  }
24221
25646
  ),
24222
- /* @__PURE__ */ (0, import_jsx_runtime33.jsx)("div", { className: "flex-1 bg-bridge-primary", style: { height: 3 } })
25647
+ /* @__PURE__ */ (0, import_jsx_runtime34.jsx)("div", { className: "flex-1 bg-bridge-primary", style: { height: 3 } })
24223
25648
  ]
24224
25649
  }
24225
25650
  ),
24226
- linkPopover && dialogPortalContainer ? /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
25651
+ linkPopover && dialogPortalContainer ? /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
24227
25652
  LinkPopover,
24228
25653
  {
24229
25654
  panelRef: linkPopoverPanelRef,
@@ -24240,7 +25665,7 @@ function OhhwellsBridge() {
24240
25665
  },
24241
25666
  linkPopover.key
24242
25667
  ) : null,
24243
- floatingPanel && floatingPanel.kind === "socials-display" ? /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
25668
+ floatingPanel && floatingPanel.kind === "socials-display" ? /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
24244
25669
  FloatingPanel,
24245
25670
  {
24246
25671
  open: true,
@@ -24250,7 +25675,7 @@ function OhhwellsBridge() {
24250
25675
  onPositionChange: setFloatingPanelPos,
24251
25676
  parentScroll: parentScrollSnap ?? parentScrollRef.current,
24252
25677
  onClose: closeFloatingPanelOnly,
24253
- children: /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
25678
+ children: /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
24254
25679
  SocialsDisplayPanel,
24255
25680
  {
24256
25681
  display: socialsDisplayFor(floatingPanel.row, editContentRef.current),
@@ -24261,7 +25686,48 @@ function OhhwellsBridge() {
24261
25686
  }
24262
25687
  )
24263
25688
  }
24264
- ) : null
25689
+ ) : null,
25690
+ floatingPanel && floatingPanel.kind === "button-style" ? (() => {
25691
+ const button = document.querySelector(
25692
+ `[data-ohw-href-key="${CSS.escape(floatingPanel.buttonId)}"]`
25693
+ );
25694
+ if (!button) return null;
25695
+ captureButtonOrigin(button);
25696
+ const tokens = tokensFromButton(button);
25697
+ const current = assignmentFor(button, editContentRef.current, tokens);
25698
+ void buttonStyleTick;
25699
+ return /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
25700
+ FloatingPanel,
25701
+ {
25702
+ open: true,
25703
+ title: floatingPanel.title,
25704
+ context: floatingPanel.context,
25705
+ icon: /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(import_lucide_react18.Brush, { className: "size-4 shrink-0", "aria-hidden": true }),
25706
+ position: floatingPanelPos,
25707
+ onPositionChange: setFloatingPanelPos,
25708
+ parentScroll: parentScrollSnap ?? parentScrollRef.current,
25709
+ onClose: closeFloatingPanelOnly,
25710
+ bodyClassName: "gap-5",
25711
+ children: /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
25712
+ ButtonStylePanel,
25713
+ {
25714
+ variants: tokens.variants,
25715
+ sizes: tokens.sizes,
25716
+ variant: current.variant,
25717
+ size: current.size,
25718
+ slotBackground: previewSlotBackground(button),
25719
+ previewLabel: (button.querySelector(
25720
+ '[data-ohw-editable="text"], [data-ohw-editable="plain"]'
25721
+ )?.textContent ?? button.textContent ?? "Book Now").trim() || "Book Now",
25722
+ onVariant: (variant) => applySelectedButtonStyle({ variant }),
25723
+ onSize: (size) => applySelectedButtonStyle({ size })
25724
+ },
25725
+ floatingPanel.key
25726
+ )
25727
+ },
25728
+ floatingPanel.key
25729
+ );
25730
+ })() : null
24265
25731
  ] }),
24266
25732
  bridgeRoot
24267
25733
  ) : null
@@ -24270,10 +25736,10 @@ function OhhwellsBridge() {
24270
25736
 
24271
25737
  // src/ui/EmptySection.tsx
24272
25738
  var import_link = __toESM(require("next/link"), 1);
24273
- var import_jsx_runtime34 = require("react/jsx-runtime");
25739
+ var import_jsx_runtime35 = require("react/jsx-runtime");
24274
25740
  function EmptySection({ title, homeHref = "/", eyebrowKey, titleKey, subtitleKey }) {
24275
- return /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)(import_jsx_runtime34.Fragment, { children: [
24276
- /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
25741
+ return /* @__PURE__ */ (0, import_jsx_runtime35.jsxs)(import_jsx_runtime35.Fragment, { children: [
25742
+ /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(
24277
25743
  "p",
24278
25744
  {
24279
25745
  style: {
@@ -24285,10 +25751,10 @@ function EmptySection({ title, homeHref = "/", eyebrowKey, titleKey, subtitleKey
24285
25751
  color: "var(--brand-accent)",
24286
25752
  marginBottom: "1.5rem"
24287
25753
  },
24288
- children: /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(import_link.default, { href: homeHref, style: { color: "inherit" }, children: /* @__PURE__ */ (0, import_jsx_runtime34.jsx)("span", { ...eyebrowKey ? { "data-ohw-editable": "text", "data-ohw-key": eyebrowKey } : {}, children: "Home" }) })
25754
+ children: /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(import_link.default, { href: homeHref, style: { color: "inherit" }, children: /* @__PURE__ */ (0, import_jsx_runtime35.jsx)("span", { ...eyebrowKey ? { "data-ohw-editable": "text", "data-ohw-key": eyebrowKey } : {}, children: "Home" }) })
24289
25755
  }
24290
25756
  ),
24291
- /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
25757
+ /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(
24292
25758
  "h1",
24293
25759
  {
24294
25760
  style: {
@@ -24303,7 +25769,7 @@ function EmptySection({ title, homeHref = "/", eyebrowKey, titleKey, subtitleKey
24303
25769
  children: title
24304
25770
  }
24305
25771
  ),
24306
- /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
25772
+ /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(
24307
25773
  "p",
24308
25774
  {
24309
25775
  style: {