@ohhwells/bridge 0.1.108-next.282 → 0.1.108

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
@@ -46,7 +46,6 @@ __export(index_exports, {
46
46
  DropdownMenuItem: () => DropdownMenuItem,
47
47
  DropdownMenuSeparator: () => DropdownMenuSeparator,
48
48
  DropdownMenuTrigger: () => DropdownMenuTrigger,
49
- EmptySection: () => EmptySection,
50
49
  ItemActionToolbar: () => ItemActionToolbar,
51
50
  ItemInteractionLayer: () => ItemInteractionLayer,
52
51
  LinkEditorPanel: () => LinkEditorPanel,
@@ -353,17 +352,16 @@ var LEGACY_BRAND_VAR_NAMES = [
353
352
  "text-muted",
354
353
  "surface",
355
354
  "border",
356
- "on-primary"
355
+ "on-primary",
356
+ "navbar-background"
357
357
  ].map((role) => `--brand-${role}`);
358
358
  var FONT_VARS = {
359
359
  heading: ["--font-heading", "--font-display", "--brand-font-heading"],
360
360
  body: ["--font-body", "--brand-font-body"]
361
361
  };
362
362
  var BRAND_FONT_LINK_ID = "ohw-brand-fonts";
363
- var CUSTOM_FONT_STYLE_ID = "ohw-brand-custom-fonts";
364
- var CUSTOM_FONT_FORMATS = /* @__PURE__ */ new Set(["woff2", "woff", "truetype", "opentype"]);
365
- function brandColorVars(palette) {
366
- const { dark, primary, accent, light } = palette;
363
+ function brandColorVars(kit) {
364
+ const { dark, primary, accent, light } = kit.palette;
367
365
  const mix = (a, aPct, b) => `color-mix(in srgb, ${a} ${aPct}%, ${b})`;
368
366
  const surface = mix(light, 95, dark);
369
367
  const border = mix(light, 85, dark);
@@ -386,42 +384,22 @@ function brandColorVars(palette) {
386
384
  "--brand-border": border,
387
385
  // Buttons/bands painted in the primary colour assume it's dark/saturated enough to need
388
386
  // light text on top — the same assumption LOGO_IMAGE's light-on-dark navbar mark makes.
389
- "--brand-on-primary": light
387
+ "--brand-on-primary": light,
388
+ "--brand-navbar-background": dark
390
389
  };
391
390
  }
392
- function parseCustomFontWeight(raw) {
393
- if (typeof raw !== "object" || raw === null) return null;
394
- const w = raw;
395
- if (typeof w.weight !== "number" || !Number.isFinite(w.weight)) return null;
396
- if (typeof w.url !== "string" || !w.url) return null;
397
- if (typeof w.format !== "string" || !CUSTOM_FONT_FORMATS.has(w.format)) return null;
398
- const weightEnd = typeof w.weightEnd === "number" && Number.isFinite(w.weightEnd) && w.weightEnd > w.weight ? w.weightEnd : void 0;
399
- return { weight: w.weight, ...weightEnd !== void 0 ? { weightEnd } : {}, url: w.url, format: w.format };
400
- }
401
- function parseCustomFont(raw) {
402
- if (typeof raw !== "object" || raw === null) return null;
403
- const f = raw;
404
- if (typeof f.family !== "string" || !f.family) return null;
405
- if (typeof f.label !== "string" || !f.label) return null;
406
- if (!Array.isArray(f.weights)) return null;
407
- const weights = f.weights.map(parseCustomFontWeight).filter((w) => w !== null);
408
- if (weights.length === 0) return null;
409
- return { family: f.family, label: f.label, weights };
410
- }
411
391
  function parseBrandKit(raw) {
412
392
  if (!raw) return null;
413
393
  try {
414
394
  const parsed = JSON.parse(raw);
415
395
  const p = parsed?.palette;
416
396
  const f = parsed?.fonts;
417
- const palette = p && typeof p.dark === "string" && typeof p.primary === "string" && typeof p.accent === "string" && typeof p.light === "string" ? { dark: p.dark, primary: p.primary, accent: p.accent, light: p.light } : void 0;
418
- const fonts = f && typeof f.heading === "string" && typeof f.body === "string" ? { heading: f.heading, body: f.body } : void 0;
419
- const customFonts = Array.isArray(parsed?.customFonts) ? parsed.customFonts.map(parseCustomFont).filter((c) => c !== null) : void 0;
420
- if (!palette && !fonts && !customFonts) return null;
397
+ if (!p || !f || typeof p.dark !== "string" || typeof p.primary !== "string" || typeof p.accent !== "string" || typeof p.light !== "string" || typeof f.heading !== "string" || typeof f.body !== "string") {
398
+ return null;
399
+ }
421
400
  return {
422
- ...palette ? { palette } : {},
423
- ...fonts ? { fonts } : {},
424
- ...customFonts ? { customFonts } : {}
401
+ palette: { dark: p.dark, primary: p.primary, accent: p.accent, light: p.light },
402
+ fonts: { heading: f.heading, body: f.body }
425
403
  };
426
404
  } catch {
427
405
  return null;
@@ -431,16 +409,11 @@ function familyOf(stack) {
431
409
  const first = stack.split(",")[0]?.trim() ?? "";
432
410
  return first.replace(/^['"]|['"]$/g, "");
433
411
  }
434
- function quoteFamily(family) {
435
- return `'${family.replace(/\\/g, "\\\\").replace(/'/g, "\\'")}'`;
436
- }
437
- var WEIGHT_SCALE = [100, 200, 300, 400, 500, 600, 700, 800, 900];
438
412
  function loadBrandFonts(families) {
439
413
  const unique = [...new Set(families.map((f) => f.trim()).filter(Boolean))];
440
414
  if (unique.length === 0) return;
441
- const weights = WEIGHT_SCALE.join(";");
442
- const spec = unique.map((f) => `family=${f.replace(/ /g, "+")}:wght@${weights}`).join("&");
443
- const href = `https://fonts.googleapis.com/css2?${spec}&display=swap`;
415
+ const spec = unique.map((f) => `${f.replace(/ /g, "+")}:400,500,600,700`).join("|");
416
+ const href = `https://fonts.googleapis.com/css?family=${spec}&display=swap`;
444
417
  let link = document.getElementById(BRAND_FONT_LINK_ID);
445
418
  if (!link) {
446
419
  link = document.createElement("link");
@@ -450,54 +423,18 @@ function loadBrandFonts(families) {
450
423
  }
451
424
  if (link.href !== href) link.href = href;
452
425
  }
453
- function escapeCssString(value) {
454
- return value.replace(/\\/g, "\\\\").replace(/'/g, "\\'");
455
- }
456
- function loadCustomFonts(fonts) {
457
- const list = fonts ?? [];
458
- let style = document.getElementById(CUSTOM_FONT_STYLE_ID);
459
- if (list.length === 0) {
460
- style?.remove();
461
- return;
462
- }
463
- if (!style) {
464
- style = document.createElement("style");
465
- style.id = CUSTOM_FONT_STYLE_ID;
466
- document.head.appendChild(style);
467
- }
468
- style.textContent = list.flatMap(
469
- (font) => font.weights.map((w) => {
470
- const weightDescriptor = w.weightEnd ? `${w.weight} ${w.weightEnd}` : `${w.weight}`;
471
- return `@font-face { font-family: '${escapeCssString(font.family)}'; src: url('${escapeCssString(w.url)}') format('${w.format}'); font-weight: ${weightDescriptor}; font-display: swap; }`;
472
- })
473
- ).join("\n");
474
- }
475
426
  function applyBrandToDom(kit) {
476
427
  const root = document.documentElement;
477
428
  if (!kit) {
478
429
  for (const name of [...BRAND_VAR_NAMES, ...LEGACY_BRAND_VAR_NAMES]) root.style.removeProperty(name);
479
430
  for (const name of [...FONT_VARS.heading, ...FONT_VARS.body]) root.style.removeProperty(name);
480
431
  document.getElementById(BRAND_FONT_LINK_ID)?.remove();
481
- document.getElementById(CUSTOM_FONT_STYLE_ID)?.remove();
482
432
  return;
483
433
  }
484
- if (kit.palette) {
485
- for (const [name, value] of Object.entries(brandColorVars(kit.palette))) root.style.setProperty(name, value);
486
- }
487
- if (kit.customFonts) {
488
- loadCustomFonts(kit.customFonts);
489
- }
490
- if (kit.fonts) {
491
- const heading = quoteFamily(kit.fonts.heading);
492
- const body = quoteFamily(kit.fonts.body);
493
- for (const name of FONT_VARS.heading) root.style.setProperty(name, heading);
494
- for (const name of FONT_VARS.body) root.style.setProperty(name, body);
495
- const customFamilies = new Set((kit.customFonts ?? []).map((f) => f.family));
496
- const googleFamilies = [familyOf(kit.fonts.heading), familyOf(kit.fonts.body)].filter(
497
- (f) => !customFamilies.has(f)
498
- );
499
- loadBrandFonts(googleFamilies);
500
- }
434
+ for (const [name, value] of Object.entries(brandColorVars(kit))) root.style.setProperty(name, value);
435
+ for (const name of FONT_VARS.heading) root.style.setProperty(name, kit.fonts.heading);
436
+ for (const name of FONT_VARS.body) root.style.setProperty(name, kit.fonts.body);
437
+ loadBrandFonts([familyOf(kit.fonts.heading), familyOf(kit.fonts.body)]);
501
438
  }
502
439
 
503
440
  // src/lib/section-styles.ts
@@ -1418,22 +1355,6 @@ function accentBandContext(brand) {
1418
1355
  function textAttrs(ctx, path) {
1419
1356
  return ctx.keyFor ? { "data-ohw-key": ctx.keyFor(path), "data-ohw-editable": "text" } : {};
1420
1357
  }
1421
- var AI_RESPONSIVE_CSS = [
1422
- "@media (max-width: 960px) {",
1423
- " [data-ai-responsive] [data-ai-grid] { grid-template-columns: repeat(2, 1fr) !important; }",
1424
- ' [data-ai-responsive] [data-ai-grid="1"] { grid-template-columns: 1fr !important; }',
1425
- "}",
1426
- "@media (max-width: 640px) {",
1427
- " [data-ai-responsive] [data-ai-grid] { grid-template-columns: 1fr !important; }",
1428
- " [data-ai-responsive] [data-ai-columns] > * { grid-column: 1 / -1 !important; }",
1429
- // Group containers flatten to a column on phones; span placements come along for free.
1430
- " [data-ai-responsive] [data-ai-group] { display: flex !important; flex-direction: column !important; }",
1431
- " [data-ai-responsive] [data-ai-group] > * { grid-column: auto !important; }",
1432
- " [data-ai-responsive] [data-ai-section-inner] { padding-left: 20px !important; padding-right: 20px !important; }",
1433
- " [data-ai-responsive] { overflow-x: hidden; }",
1434
- " [data-ai-responsive] img { max-width: 100%; }",
1435
- "}"
1436
- ].join("\n");
1437
1358
  var TRANSPARENT_PX = "data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7";
1438
1359
  function MediaBox({
1439
1360
  refValue,
@@ -1446,17 +1367,13 @@ function MediaBox({
1446
1367
  const url = refValue ? ctx.resolveMedia(refValue) : null;
1447
1368
  const isIcon = /^(lucide|simple):/.test(refValue);
1448
1369
  const aspectRatio = aspect && /^\d+:\d+$/.test(aspect) ? aspect.replace(":", " / ") : void 0;
1449
- const editAttrs = ctx.keyFor && editPath ? {
1450
- "data-ohw-key": ctx.keyFor(editPath),
1451
- "data-ohw-editable": isIcon ? "icon" : "image"
1452
- } : {};
1370
+ const editAttrs = ctx.keyFor && editPath && !isIcon ? { "data-ohw-key": ctx.keyFor(editPath), "data-ohw-editable": "image" } : {};
1453
1371
  if (isIcon) {
1454
1372
  const Icon = refValue.startsWith("lucide:") ? lucideByName(refValue.slice(7)) : null;
1455
1373
  return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1456
1374
  "span",
1457
1375
  {
1458
1376
  "data-ai-icon": refValue,
1459
- ...editAttrs,
1460
1377
  style: {
1461
1378
  display: "inline-flex",
1462
1379
  width: 48,
@@ -2349,7 +2266,7 @@ function CollectionBlock({ node, ctx, path }) {
2349
2266
  return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
2350
2267
  "div",
2351
2268
  {
2352
- "data-ai-grid": String(itemsPerRow),
2269
+ "data-ai-grid": "",
2353
2270
  style: {
2354
2271
  display: "grid",
2355
2272
  gridTemplateColumns: `repeat(${itemsPerRow}, 1fr)`,
@@ -2702,7 +2619,6 @@ function AiTreeRenderer({
2702
2619
  {
2703
2620
  "data-ai-section": tree.tag ?? "",
2704
2621
  ...bgAttrs,
2705
- "data-ai-responsive": "",
2706
2622
  style: {
2707
2623
  position: "relative",
2708
2624
  padding: `${pad}px 0`,
@@ -2713,13 +2629,12 @@ function AiTreeRenderer({
2713
2629
  color: settings.sectionBackground === "accent" ? blockBrand.palette.dark : void 0
2714
2630
  },
2715
2631
  children: [
2716
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("style", { children: AI_RESPONSIVE_CSS }),
2717
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("style", { children: AI_MOBILE_CSS }),
2718
2632
  isOverlay && backgroundUrl && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: { position: "absolute", inset: 0, background: `rgba(255,255,255,${overlayAlpha})` } }),
2633
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("style", { children: AI_MOBILE_CSS }),
2719
2634
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
2720
2635
  "div",
2721
2636
  {
2722
- "data-ai-section-inner": "",
2637
+ "data-ai-container": "",
2723
2638
  style: {
2724
2639
  position: "relative",
2725
2640
  maxWidth: AI_TREE_TOKENS.sectionMaxWidth,
@@ -2730,7 +2645,7 @@ function AiTreeRenderer({
2730
2645
  children: tree.rows.map((row, r2) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
2731
2646
  "div",
2732
2647
  {
2733
- "data-ai-columns": "",
2648
+ "data-ai-row": "",
2734
2649
  style: {
2735
2650
  display: "grid",
2736
2651
  gridTemplateColumns: "repeat(12, 1fr)",
@@ -2780,52 +2695,14 @@ function readRootVar(name) {
2780
2695
  if (typeof document === "undefined") return "";
2781
2696
  return getComputedStyle(document.documentElement).getPropertyValue(name).trim();
2782
2697
  }
2783
- function normalizeColorToHex(value) {
2784
- if (!value || typeof document === "undefined") return value;
2785
- const canvas = document.createElement("canvas");
2786
- canvas.width = 1;
2787
- canvas.height = 1;
2788
- const ctx = canvas.getContext("2d");
2789
- if (!ctx) return value;
2790
- ctx.fillStyle = value;
2791
- ctx.fillRect(0, 0, 1, 1);
2792
- const [r2, g, b] = ctx.getImageData(0, 0, 1, 1).data;
2793
- const toHex = (n) => n.toString(16).padStart(2, "0");
2794
- return `#${toHex(r2)}${toHex(g)}${toHex(b)}`;
2795
- }
2796
- var GENERIC_FONT_KEYWORDS = /* @__PURE__ */ new Set([
2797
- "serif",
2798
- "sans-serif",
2799
- "monospace",
2800
- "cursive",
2801
- "fantasy",
2802
- "system-ui",
2803
- "ui-serif",
2804
- "ui-sans-serif",
2805
- "ui-monospace",
2806
- "ui-rounded",
2807
- "math",
2808
- "emoji",
2809
- "fangsong"
2810
- ]);
2811
- function primaryFontFamily(stack) {
2812
- const first = stack.split(",").map((part) => part.trim().replace(/^["']|["']$/g, "")).find((part) => part && !GENERIC_FONT_KEYWORDS.has(part.toLowerCase()));
2813
- return first ?? "";
2814
- }
2815
- function humanizeFontFamily(name) {
2816
- return name.replace(/^__/, "").replace(/_[0-9a-f]{6}$/i, "").replace(/_/g, " ").replace(/([a-z0-9])([A-Z])/g, "$1 $2").trim().replace(/\s+/g, " ").replace(/(^|\s)([a-z])/g, (_, sep, c) => sep + c.toUpperCase());
2817
- }
2818
- function readFontVar(name) {
2819
- return humanizeFontFamily(primaryFontFamily(readRootVar(name)));
2820
- }
2821
2698
  function deriveBrandOverride() {
2822
2699
  const dark = readRootVar("--ohw-brand-dark");
2823
2700
  const primary = readRootVar("--ohw-brand-primary");
2824
2701
  const light = readRootVar("--ohw-brand-light");
2825
2702
  if (!dark || !primary || !light) return null;
2826
2703
  const accent = readRootVar("--ohw-brand-accent");
2827
- const heading = readFontVar("--font-heading") || readFontVar("--font-display");
2828
- const body = readFontVar("--font-body");
2704
+ const heading = readRootVar("--font-heading") || readRootVar("--font-display");
2705
+ const body = readRootVar("--font-body");
2829
2706
  return {
2830
2707
  palette: { dark, primary, accent: accent || dark, light },
2831
2708
  fonts: {
@@ -2834,55 +2711,22 @@ function deriveBrandOverride() {
2834
2711
  }
2835
2712
  };
2836
2713
  }
2837
- function deriveTemplateBrandLive() {
2838
- const dark = readRootVar("--color-dark") || readRootVar("--brand-text");
2839
- const primary = readRootVar("--color-primary") || readRootVar("--brand-primary");
2840
- const light = readRootVar("--color-light") || readRootVar("--brand-background");
2714
+ function deriveTemplateBrand() {
2715
+ const primary = readRootVar("--brand-primary") || readRootVar("--color-primary");
2716
+ const dark = readRootVar("--brand-text") || readRootVar("--color-dark");
2717
+ const light = readRootVar("--brand-background") || readRootVar("--color-light");
2841
2718
  if (!dark || !primary || !light) return null;
2842
- const accent = readRootVar("--color-accent") || readRootVar("--brand-accent");
2843
- const heading = readFontVar("--brand-font-heading") || readFontVar("--font-heading") || readFontVar("--font-display");
2844
- const body = readFontVar("--brand-font-body") || readFontVar("--font-body");
2719
+ const accent = readRootVar("--brand-accent") || readRootVar("--color-accent");
2720
+ const heading = readRootVar("--brand-font-heading") || readRootVar("--font-heading") || readRootVar("--font-display");
2721
+ const body = readRootVar("--brand-font-body") || readRootVar("--font-body");
2845
2722
  return {
2846
- palette: {
2847
- dark: normalizeColorToHex(dark),
2848
- primary: normalizeColorToHex(primary),
2849
- accent: normalizeColorToHex(accent || dark),
2850
- light: normalizeColorToHex(light)
2851
- },
2723
+ palette: { dark, primary, accent: accent || dark, light },
2852
2724
  fonts: {
2853
2725
  heading: heading || AI_DEFAULT_BRAND.fonts.heading,
2854
2726
  body: body || AI_DEFAULT_BRAND.fonts.body
2855
2727
  }
2856
2728
  };
2857
2729
  }
2858
- function deriveTemplateFontsLive() {
2859
- const heading = readFontVar("--brand-font-heading") || readFontVar("--font-heading") || readFontVar("--font-display");
2860
- const body = readFontVar("--brand-font-body") || readFontVar("--font-body");
2861
- if (!heading && !body) return null;
2862
- return {
2863
- heading: heading || AI_DEFAULT_BRAND.fonts.heading,
2864
- body: body || AI_DEFAULT_BRAND.fonts.body
2865
- };
2866
- }
2867
- var OVERRIDE_VAR_NAMES = [...BRAND_VAR_NAMES, ...LEGACY_BRAND_VAR_NAMES, ...FONT_VARS.heading, ...FONT_VARS.body];
2868
- function withOverrideStripped(read) {
2869
- const root = document.documentElement;
2870
- const restore = OVERRIDE_VAR_NAMES.map((name) => [name, root.style.getPropertyValue(name)]);
2871
- for (const name of OVERRIDE_VAR_NAMES) root.style.removeProperty(name);
2872
- try {
2873
- return read();
2874
- } finally {
2875
- for (const [name, value] of restore) if (value) root.style.setProperty(name, value);
2876
- }
2877
- }
2878
- var TEMPLATE_BRAND_SNAPSHOT = typeof document === "undefined" ? null : withOverrideStripped(deriveTemplateBrandLive);
2879
- var TEMPLATE_FONTS_SNAPSHOT = typeof document === "undefined" ? null : withOverrideStripped(deriveTemplateFontsLive);
2880
- function deriveTemplateBrand() {
2881
- return TEMPLATE_BRAND_SNAPSHOT;
2882
- }
2883
- function deriveTemplateFonts() {
2884
- return TEMPLATE_FONTS_SNAPSHOT;
2885
- }
2886
2730
  function deriveTemplateButtonStyle() {
2887
2731
  if (typeof document === "undefined") return null;
2888
2732
  const candidates = Array.from(
@@ -7380,12 +7224,12 @@ var cva = (base, config) => (props) => {
7380
7224
  var import_radix_ui2 = require("radix-ui");
7381
7225
  var import_jsx_runtime5 = require("react/jsx-runtime");
7382
7226
  var toggleVariants = cva(
7383
- "inline-flex items-center justify-center gap-2 rounded-md text-sm font-medium whitespace-nowrap transition-[color,box-shadow] outline-none hover:bg-muted hover:text-muted-foreground focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50 disabled:pointer-events-none disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-destructive/20 data-[state=on]:bg-bridge-accent data-[state=on]:text-accent-foreground [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
7227
+ "inline-flex items-center justify-center gap-2 rounded-md text-sm font-medium whitespace-nowrap transition-[color,box-shadow] outline-none hover:bg-muted hover:text-muted-foreground focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50 disabled:pointer-events-none disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-destructive/20 data-[state=on]:bg-accent data-[state=on]:text-accent-foreground [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
7384
7228
  {
7385
7229
  variants: {
7386
7230
  variant: {
7387
7231
  default: "bg-transparent border-0",
7388
- outline: "border border-input bg-transparent shadow-xs hover:bg-bridge-accent hover:text-accent-foreground"
7232
+ outline: "border border-input bg-transparent shadow-xs hover:bg-accent hover:text-accent-foreground"
7389
7233
  },
7390
7234
  size: {
7391
7235
  default: "px-2 py-1",
@@ -7478,10 +7322,10 @@ var DragHandle = React4.forwardRef(
7478
7322
  type,
7479
7323
  "data-slot": "drag-handle",
7480
7324
  className: cn(
7481
- "inline-flex h-7 w-4 shrink-0 items-center justify-center rounded-md transition-all duration-200 max-h-7.5",
7325
+ "inline-flex h-7 w-4 shrink-0 items-center justify-center rounded-md transition-all duration-200 max-h-[30px]",
7482
7326
  "bg-white border border-transparent text-stone-500 shadow-md cursor-grab",
7483
7327
  "enabled:hover:border enabled:hover:border-stone-200 enabled:hover:text-stone-950",
7484
- "enabled:active:border enabled:active:border-bridge-primary enabled:active:bg-primary-50 enabled:active:text-stone-950 enabled:active:shadow enabled:active:cursor-grabbing",
7328
+ "enabled:active:border enabled:active:border-primary enabled:active:bg-primary-50 enabled:active:text-stone-950 enabled:active:shadow enabled:active:cursor-grabbing",
7485
7329
  "disabled:cursor-not-allowed disabled:opacity-40 disabled:text-stone-950 disabled:pointer-events-none",
7486
7330
  className
7487
7331
  ),
@@ -7503,7 +7347,7 @@ var CustomToolbar = React5.forwardRef(({ className, onMouseDown, ...props }, ref
7503
7347
  "data-ohw-toolbar": "",
7504
7348
  className: cn(
7505
7349
  // Figma: bg background, radius 8, gap-1, p-0.5, shadow-md — no border
7506
- "inline-flex h-8 items-center gap-1 rounded-(--radius,0.5rem) bg-background p-0.5 font-sans whitespace-nowrap shadow-md",
7350
+ "inline-flex h-8 items-center gap-1 rounded-[var(--radius,0.5rem)] bg-background p-0.5 font-sans whitespace-nowrap shadow-md",
7507
7351
  className
7508
7352
  ),
7509
7353
  onMouseDown: (e) => {
@@ -7532,7 +7376,7 @@ var CustomToolbarButton = React5.forwardRef(
7532
7376
  type,
7533
7377
  className: cn(
7534
7378
  "inline-flex size-7 shrink-0 items-center justify-center rounded-[calc(var(--radius,0.5rem)-2px)] text-foreground transition-colors",
7535
- active ? "bg-bridge-primary text-primary-foreground" : "bg-transparent hover:bg-muted disabled:cursor-not-allowed disabled:text-muted-foreground disabled:opacity-60",
7379
+ active ? "bg-primary text-primary-foreground" : "bg-transparent hover:bg-muted disabled:cursor-not-allowed disabled:text-muted-foreground disabled:opacity-60",
7536
7380
  className
7537
7381
  ),
7538
7382
  ...props
@@ -8734,13 +8578,13 @@ function FormFieldToolbar({
8734
8578
  ]
8735
8579
  }
8736
8580
  ) }),
8737
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(DropdownMenuContent, { align: "start", sideOffset: 8, className: "min-w-47.5 p-1", children: FIELD_TYPES.map((entry) => {
8581
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(DropdownMenuContent, { align: "start", sideOffset: 8, className: "min-w-[190px] p-1", children: FIELD_TYPES.map((entry) => {
8738
8582
  const Icon = TYPE_ICONS[entry.type];
8739
8583
  return /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(
8740
8584
  DropdownMenuItem,
8741
8585
  {
8742
8586
  onSelect: () => onTypeChange(entry.type),
8743
- className: "rounded-md py-2 text-[13px] " + (entry.type === type ? "bg-bridge-primary/10" : ""),
8587
+ className: "rounded-md py-2 text-[13px] " + (entry.type === type ? "bg-primary/10" : ""),
8744
8588
  children: [
8745
8589
  /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(Icon, { size: 14, strokeWidth: 1.75, className: "shrink-0", "aria-hidden": true }),
8746
8590
  entry.label
@@ -8757,7 +8601,7 @@ function FormFieldToolbar({
8757
8601
  type: "button",
8758
8602
  "aria-pressed": required,
8759
8603
  onClick: onRequiredToggle,
8760
- className: "flex h-7 items-center gap-1.5 whitespace-nowrap rounded-md px-2 text-[13px] font-medium transition-colors " + (required ? "bg-bridge-primary/10 text-bridge-primary" : "text-foreground hover:bg-muted/70"),
8604
+ className: "flex h-7 items-center gap-1.5 whitespace-nowrap rounded-md px-2 text-[13px] font-medium transition-colors " + (required ? "bg-primary/10 text-primary" : "text-foreground hover:bg-muted/70"),
8761
8605
  "data-ohw-field-required-toggle": "",
8762
8606
  children: [
8763
8607
  /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_lucide_react4.Asterisk, { size: 14, strokeWidth: 2, "aria-hidden": true }),
@@ -8777,7 +8621,7 @@ function FormFieldToolbar({
8777
8621
  children: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_lucide_react4.MoreHorizontal, { size: 15, "aria-hidden": true })
8778
8622
  }
8779
8623
  ) }),
8780
- /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(DropdownMenuContent, { align: "start", sideOffset: 8, className: "min-w-42.5 p-1", children: [
8624
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(DropdownMenuContent, { align: "start", sideOffset: 8, className: "min-w-[170px] p-1", children: [
8781
8625
  /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(DropdownMenuItem, { onSelect: onDuplicate, className: "rounded-md py-2 text-[13px]", children: [
8782
8626
  /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_lucide_react4.Copy, { size: 14, strokeWidth: 1.75, className: "shrink-0", "aria-hidden": true }),
8783
8627
  "Duplicate"
@@ -8797,7 +8641,7 @@ function FieldTypePicker({ onPick }) {
8797
8641
  "div",
8798
8642
  {
8799
8643
  "data-ohw-field-type-picker": "",
8800
- className: "pointer-events-auto grid w-105 grid-cols-3 gap-3 rounded-xl border border-border bg-background p-4 shadow-lg",
8644
+ className: "pointer-events-auto grid w-[280px] grid-cols-2 gap-2 rounded-xl border border-border bg-background p-3 shadow-lg",
8801
8645
  children: FIELD_TYPES.map((entry) => {
8802
8646
  const Icon = TYPE_ICONS[entry.type];
8803
8647
  return /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(
@@ -8805,7 +8649,7 @@ function FieldTypePicker({ onPick }) {
8805
8649
  {
8806
8650
  type: "button",
8807
8651
  onClick: () => onPick(entry.type),
8808
- className: "flex h-26 flex-col items-center justify-center gap-3 rounded-xl border border-border text-[15px] font-medium text-foreground transition-colors hover:border-bridge-primary hover:bg-bridge-primary/5",
8652
+ className: "flex h-[76px] flex-col items-center justify-center gap-2 rounded-xl border border-border text-[15px] font-medium text-foreground transition-colors hover:border-primary hover:bg-primary/5",
8809
8653
  children: [
8810
8654
  /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(Icon, { size: 26, strokeWidth: 1.5, "aria-hidden": true }),
8811
8655
  entry.label
@@ -8831,7 +8675,7 @@ var buttonVariants = cva(
8831
8675
  {
8832
8676
  variants: {
8833
8677
  variant: {
8834
- default: "bg-bridge-primary text-primary-foreground hover:opacity-90",
8678
+ default: "bg-primary text-primary-foreground hover:opacity-90",
8835
8679
  outline: "border border-border bg-background text-foreground shadow-sm hover:bg-muted/80",
8836
8680
  ghost: "min-w-0 px-3 py-2 text-foreground hover:bg-muted/50"
8837
8681
  },
@@ -8926,7 +8770,6 @@ function MediaOverlay({
8926
8770
  (prev) => prev && prev.fullWidth === width && prev.height === height ? prev : { fullWidth: width, height }
8927
8771
  );
8928
8772
  }, [isVideo]);
8929
- const replaceLabel = isVideo ? "Replace video" : hover.elementType === "bg-image" ? "Replace background" : "Replace image";
8930
8773
  const replaceMode = buttonSize ? replaceButtonMode({ width: rect.width, height: rect.height }, buttonSize) : "none";
8931
8774
  const box = {
8932
8775
  position: "fixed",
@@ -9032,8 +8875,8 @@ function MediaOverlay({
9032
8875
  pointerEvents: hover.hasTextOverlap ? "none" : "auto",
9033
8876
  // Selected: a firm component ring with no wash, so the image reads as chosen rather
9034
8877
  // than hovered. Hover keeps the existing tinted preview.
9035
- boxShadow: selected ? "inset 0 0 0 2px var(--color-bridge-primary)" : "inset 0 0 0 1.5px var(--color-bridge-primary)",
9036
- background: selected ? "transparent" : "color-mix(in srgb, var(--color-bridge-primary) 20%, transparent)"
8878
+ boxShadow: selected ? "inset 0 0 0 2px var(--color-primary)" : "inset 0 0 0 1.5px var(--color-primary)",
8879
+ background: selected ? "transparent" : "color-mix(in srgb, var(--color-primary) 20%, transparent)"
9037
8880
  },
9038
8881
  onClick: () => onSelect && !selected ? onSelect(hover.key) : onReplace(hover.key),
9039
8882
  children: [
@@ -9056,17 +8899,17 @@ function MediaOverlay({
9056
8899
  },
9057
8900
  children: [
9058
8901
  isVideo ? /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(import_lucide_react5.Film, { size: 14 }) : /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(import_lucide_react5.ImageIcon, { size: 14 }),
9059
- replaceLabel
8902
+ isVideo ? "Replace video" : "Replace image"
9060
8903
  ]
9061
8904
  }
9062
8905
  ),
9063
- showChrome && replaceMode !== "none" && /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(
8906
+ replaceMode === "none" ? null : /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(
9064
8907
  Button,
9065
8908
  {
9066
8909
  "data-ohw-media-overlay": "",
9067
8910
  variant: "outline",
9068
8911
  size: "sm",
9069
- "aria-label": replaceLabel,
8912
+ "aria-label": isVideo ? "Replace video" : "Replace image",
9070
8913
  className: "gap-1.5 cursor-pointer hover:bg-background",
9071
8914
  style: {
9072
8915
  ...OVERLAY_BUTTON_STYLE,
@@ -9089,7 +8932,7 @@ function MediaOverlay({
9089
8932
  },
9090
8933
  children: [
9091
8934
  isVideo ? /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(import_lucide_react5.Film, { size: 14 }) : /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(import_lucide_react5.ImageIcon, { size: 14 }),
9092
- replaceMode === "full" ? replaceLabel : null
8935
+ replaceMode === "full" ? isVideo ? "Replace video" : hover.elementType === "bg-image" ? "Replace background" : "Replace image" : null
9093
8936
  ]
9094
8937
  }
9095
8938
  )
@@ -9127,8 +8970,8 @@ function CarouselOverlay({
9127
8970
  height: rect.height,
9128
8971
  zIndex: 2147483646,
9129
8972
  pointerEvents: "auto",
9130
- boxShadow: "inset 0 0 0 1.5px var(--color-bridge-primary)",
9131
- background: "color-mix(in srgb, var(--color-bridge-primary) 20%, transparent)"
8973
+ boxShadow: "inset 0 0 0 1.5px var(--color-primary)",
8974
+ background: "color-mix(in srgb, var(--color-primary) 20%, transparent)"
9132
8975
  },
9133
8976
  onClick: () => onEdit(hover.key),
9134
8977
  children: /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(
@@ -9966,7 +9809,7 @@ function SectionTreeItem({
9966
9809
  /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
9967
9810
  "div",
9968
9811
  {
9969
- className: "-mr-px h-9 w-2 shrink-0 rounded-bl-sm border-b border-l border-border mb-4",
9812
+ className: "mr-[-1px] h-9 w-2 shrink-0 rounded-bl-sm border-b border-l border-border mb-4",
9970
9813
  "aria-hidden": true
9971
9814
  }
9972
9815
  ),
@@ -9985,7 +9828,7 @@ function SectionTreeItem({
9985
9828
  className: cn(
9986
9829
  "flex h-9 min-w-0 flex-1 items-center gap-2 rounded-md border border-border bg-background p-3",
9987
9830
  interactive && "cursor-pointer hover:bg-muted/30",
9988
- interactive && selected && "border-bridge-primary"
9831
+ interactive && selected && "border-primary"
9989
9832
  ),
9990
9833
  children: [
9991
9834
  /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
@@ -10115,7 +9958,7 @@ function UrlOrPageInput({
10115
9958
  };
10116
9959
  const fieldClassName = cn(
10117
9960
  "data-ohw-link-field flex h-[36px] w-full items-center overflow-hidden rounded-md border bg-background pl-3 pr-3 py-2 outline-none transition-[border-color,box-shadow]",
10118
- urlError ? "border-destructive shadow-[0_0_0_1px_var(--ohw-destructive)]" : isFocused ? "border-bridge-primary shadow-[0_0_0_1px_var(--ohw-primary)]" : "border-input"
9961
+ urlError ? "border-destructive shadow-[0_0_0_1px_var(--ohw-destructive)]" : isFocused ? "border-primary shadow-[0_0_0_1px_var(--ohw-primary)]" : "border-input"
10119
9962
  );
10120
9963
  return /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { className: "flex w-full flex-col gap-2 p-0", children: [
10121
9964
  /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(Label, { htmlFor: inputId, className: cn(urlError && "text-destructive"), children: "Destination" }),
@@ -13964,7 +13807,6 @@ function readLogoSizeState(content, placement) {
13964
13807
  function getLogoElement(el) {
13965
13808
  const marked = el.closest('[data-ohw-role="logo"], [data-ohw-logo]');
13966
13809
  if (marked) return marked;
13967
- if (el.closest('[data-ohw-editable="icon"]')) return null;
13968
13810
  const root = el.closest("nav, [data-ohw-nav-root], footer");
13969
13811
  if (!root) return null;
13970
13812
  const anchor = el.closest("a");
@@ -14252,7 +14094,7 @@ function DisplaySwitch({
14252
14094
  onClick: () => onChange(!checked),
14253
14095
  className: cn(
14254
14096
  "relative h-5 w-9 shrink-0 rounded-full transition-colors",
14255
- checked ? "bg-bridge-primary" : "bg-primary-50",
14097
+ checked ? "bg-primary" : "bg-primary-50",
14256
14098
  disabled ? "cursor-default opacity-50" : "cursor-pointer"
14257
14099
  ),
14258
14100
  children: /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
@@ -14260,7 +14102,7 @@ function DisplaySwitch({
14260
14102
  {
14261
14103
  className: cn(
14262
14104
  "absolute top-0.5 h-4 w-4 rounded-full bg-white transition-all",
14263
- checked ? "left-4.5" : "left-0.5"
14105
+ checked ? "left-[1.125rem]" : "left-0.5"
14264
14106
  )
14265
14107
  }
14266
14108
  )
@@ -15878,7 +15720,7 @@ var badgeVariants = cva(
15878
15720
  {
15879
15721
  variants: {
15880
15722
  variant: {
15881
- default: "border-transparent bg-bridge-primary text-primary-foreground",
15723
+ default: "border-transparent bg-primary text-primary-foreground",
15882
15724
  secondary: "border-transparent bg-secondary text-secondary-foreground hover:bg-secondary/80",
15883
15725
  destructive: "border-transparent bg-destructive text-destructive-foreground hover:bg-destructive/80",
15884
15726
  outline: "text-foreground"
@@ -16060,10 +15902,21 @@ function parseSchedulingInsertAfter(insertAfter) {
16060
15902
  insertBefore: insertAfter.slice(idx + INSERT_BEFORE_MARKER.length)
16061
15903
  };
16062
15904
  }
16063
- function resolveEntryAnchor(entry) {
16064
- if (entry.anchorId !== void 0) return { anchorId: entry.anchorId, beforeId: entry.beforeId ?? null };
16065
- const parsed = parseSchedulingInsertAfter(entry.insertAfter);
16066
- return { anchorId: parsed.anchor, beforeId: parsed.insertBefore };
15905
+ function resolveSchedulingInsert(insertAfter, explicitInsertBefore) {
15906
+ const parsed = parseSchedulingInsertAfter(insertAfter);
15907
+ const insertBefore = explicitInsertBefore ?? parsed.insertBefore;
15908
+ const effectiveInsertAfter = insertBefore && parsed.insertBefore === null ? `${insertAfter}${INSERT_BEFORE_MARKER}${insertBefore}` : insertAfter;
15909
+ return { effectiveInsertAfter, insertBefore };
15910
+ }
15911
+ function getSchedulingMountPoint(insertAfter) {
15912
+ const { anchor } = parseSchedulingInsertAfter(insertAfter);
15913
+ let anchorEl = document.querySelector(`[data-ohw-section="${anchor}"]`);
15914
+ if (!anchorEl && anchor === "scheduling") {
15915
+ const widgets = Array.from(document.querySelectorAll('[data-ohw-section^="scheduling-"]'));
15916
+ anchorEl = widgets.at(-1) ?? null;
15917
+ }
15918
+ if (!anchorEl) return null;
15919
+ return anchorEl.closest('[data-ohw-section-container="scheduling"]') ?? anchorEl;
16067
15920
  }
16068
15921
  function schedulingMountDepth(insertAfter) {
16069
15922
  if (!insertAfter.includes(INSERT_BEFORE_MARKER)) return 0;
@@ -16080,7 +15933,8 @@ function getPageSchedulingEntries(raw) {
16080
15933
  }
16081
15934
  }
16082
15935
  function isSchedulingWidgetMissing(entry) {
16083
- return !document.querySelector(`[data-ohw-section="${schedulingSectionId(entry.insertAfter)}"]`);
15936
+ const { effectiveInsertAfter } = resolveSchedulingInsert(entry.insertAfter);
15937
+ return !document.querySelector(`[data-ohw-section="${schedulingSectionId(effectiveInsertAfter)}"]`);
16084
15938
  }
16085
15939
  function hasMissingSchedulingWidgets(entries) {
16086
15940
  return entries.some(isSchedulingWidgetMissing);
@@ -16118,18 +15972,17 @@ function initSectionsFromContent(content, removeExisting = false, currentPath =
16118
15972
  } catch {
16119
15973
  }
16120
15974
  }
16121
- function mountSchedulingWidget(anchorId, notifyOnConnect = false, scheduleId, beforeId, existingWidgetId) {
16122
- const widgetId = existingWidgetId ?? (beforeId ? `${anchorId}${INSERT_BEFORE_MARKER}${beforeId}` : anchorId);
16123
- const sectionId = schedulingSectionId(widgetId);
15975
+ function mountSchedulingWidget(insertAfter, notifyOnConnect = false, scheduleId, explicitInsertBefore) {
15976
+ const { effectiveInsertAfter, insertBefore } = resolveSchedulingInsert(insertAfter, explicitInsertBefore);
15977
+ const sectionId = schedulingSectionId(effectiveInsertAfter);
16124
15978
  if (document.querySelector(`[data-ohw-section="${sectionId}"]`)) return false;
16125
- const anchorEl = document.querySelector(`[data-ohw-section="${anchorId}"]`);
16126
- if (!anchorEl) return false;
16127
- const mountPoint = anchorEl.closest('[data-ohw-section-container="scheduling"]') ?? anchorEl;
15979
+ const mountPoint = getSchedulingMountPoint(effectiveInsertAfter);
15980
+ if (!mountPoint) return false;
16128
15981
  const container = document.createElement("div");
16129
15982
  container.dataset.ohwSectionContainer = "scheduling";
16130
15983
  container.dataset.ohwInstance = sectionId;
16131
- if (beforeId) {
16132
- const beforeAnchor = document.querySelector(`[data-ohw-section="${beforeId}"]`);
15984
+ if (insertBefore) {
15985
+ const beforeAnchor = document.querySelector(`[data-ohw-section="${insertBefore}"]`);
16133
15986
  const beforePoint = beforeAnchor?.closest('[data-ohw-section-container="scheduling"]') ?? beforeAnchor;
16134
15987
  if (!beforePoint) return false;
16135
15988
  beforePoint.insertAdjacentElement("beforebegin", container);
@@ -16140,26 +15993,20 @@ function mountSchedulingWidget(anchorId, notifyOnConnect = false, scheduleId, be
16140
15993
  }
16141
15994
  tail.insertAdjacentElement("afterend", container);
16142
15995
  }
16143
- try {
16144
- const root = (0, import_client2.createRoot)(container);
16145
- schedulingRoots.set(container, root);
16146
- (0, import_react_dom3.flushSync)(() => {
16147
- root.render(
16148
- /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
16149
- SchedulingWidget,
16150
- {
16151
- notifyOnConnect,
16152
- initialScheduleId: scheduleId,
16153
- insertAfter: widgetId
16154
- }
16155
- )
16156
- );
16157
- });
16158
- } catch (err) {
16159
- console.error("[ow:scheduling] render threw", err);
16160
- container.remove();
16161
- return false;
16162
- }
15996
+ const root = (0, import_client2.createRoot)(container);
15997
+ schedulingRoots.set(container, root);
15998
+ (0, import_react_dom3.flushSync)(() => {
15999
+ root.render(
16000
+ /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
16001
+ SchedulingWidget,
16002
+ {
16003
+ notifyOnConnect,
16004
+ initialScheduleId: scheduleId,
16005
+ insertAfter: effectiveInsertAfter
16006
+ }
16007
+ )
16008
+ );
16009
+ });
16163
16010
  const tracker = getSectionsTracker();
16164
16011
  let sections = [];
16165
16012
  try {
@@ -16167,12 +16014,10 @@ function mountSchedulingWidget(anchorId, notifyOnConnect = false, scheduleId, be
16167
16014
  } catch {
16168
16015
  }
16169
16016
  const inEditor = typeof window !== "undefined" && window.self !== window.top;
16170
- if (inEditor && !sections.find((s) => s.type === "scheduling" && s.insertAfter === widgetId)) {
16017
+ if (inEditor && !sections.find((s) => s.type === "scheduling" && s.insertAfter === effectiveInsertAfter)) {
16171
16018
  sections.push({
16172
16019
  type: "scheduling",
16173
- insertAfter: widgetId,
16174
- anchorId,
16175
- beforeId: beforeId ?? null,
16020
+ insertAfter: effectiveInsertAfter,
16176
16021
  pagePath: window.location.pathname,
16177
16022
  ...scheduleId ? { scheduleId } : {}
16178
16023
  });
@@ -16186,8 +16031,7 @@ function mountSchedulingEntries(entries, notifyOnConnect = false) {
16186
16031
  for (let i = pending.length - 1; i >= 0; i--) {
16187
16032
  const entry = pending[i];
16188
16033
  const shouldNotify = typeof notifyOnConnect === "function" ? notifyOnConnect(entry) : notifyOnConnect;
16189
- const { anchorId, beforeId } = resolveEntryAnchor(entry);
16190
- if (mountSchedulingWidget(anchorId, shouldNotify, entry.scheduleId ?? null, beforeId, entry.insertAfter)) {
16034
+ if (mountSchedulingWidget(entry.insertAfter, shouldNotify, entry.scheduleId ?? null)) {
16191
16035
  pending.splice(i, 1);
16192
16036
  }
16193
16037
  }
@@ -16351,11 +16195,6 @@ function applyLinkByKey(key, val) {
16351
16195
  hrefAnchors.forEach((el) => applyLinkHref(el, val));
16352
16196
  }
16353
16197
  }
16354
- function isInsideLinkEditor(target) {
16355
- return Boolean(
16356
- target.closest("[data-ohw-link-popover-root]") || target.closest("[data-ohw-link-modal-root]") || target.closest("[data-ohw-link-page-dropdown]") || target.closest("[data-ohw-section-picker]") || target.closest("[data-ohw-navbar-container-chrome]") || target.closest("[data-ohw-navbar-add-button]") || target.closest("[data-ohw-footer-container-chrome]") || target.closest("[data-ohw-footer-add-button]") || target.closest("[data-ohw-more-menu]") || target.closest('[data-slot="dropdown-menu-content"]') || target.closest('[data-slot="popover-content"]') || target.closest('[data-slot="dialog-content"]') || target.closest('[data-slot="dialog-overlay"]')
16357
- );
16358
- }
16359
16198
  function isInsideFloatingPanel(target) {
16360
16199
  return Boolean(target.closest("[data-ohw-floating-panel]"));
16361
16200
  }
@@ -16363,6 +16202,11 @@ function isPointOverFloatingPanel(clientX, clientY) {
16363
16202
  const el = document.elementFromPoint(clientX, clientY);
16364
16203
  return Boolean(el instanceof Element && el.closest("[data-ohw-floating-panel]"));
16365
16204
  }
16205
+ function isInsideLinkEditor(target) {
16206
+ return Boolean(
16207
+ target.closest("[data-ohw-link-popover-root]") || target.closest("[data-ohw-link-modal-root]") || target.closest("[data-ohw-link-page-dropdown]") || target.closest("[data-ohw-section-picker]") || target.closest("[data-ohw-navbar-container-chrome]") || target.closest("[data-ohw-navbar-add-button]") || target.closest("[data-ohw-footer-container-chrome]") || target.closest("[data-ohw-footer-add-button]") || target.closest("[data-ohw-more-menu]") || target.closest('[data-slot="dropdown-menu-content"]') || target.closest('[data-slot="popover-content"]') || target.closest('[data-slot="dialog-content"]') || target.closest('[data-slot="dialog-overlay"]')
16208
+ );
16209
+ }
16366
16210
  function getHrefKeyFromElement(el) {
16367
16211
  if (!el) return null;
16368
16212
  const anchor = el.closest("[data-ohw-href-key]");
@@ -16627,7 +16471,7 @@ function getNavigationSelectionParent(el) {
16627
16471
  if (!isFooterLinksContainer(el) && (el.hasAttribute("data-ohw-footer-col") || el.hasAttribute("data-ohw-footer-column") || isInferredFooterGroup2(el))) {
16628
16472
  return getFooterLinksContainer();
16629
16473
  }
16630
- if (el.hasAttribute("data-ohw-nav-container") || el.hasAttribute("data-ohw-nav-drawer") || el.hasAttribute("data-ohw-footer-col") || el.hasAttribute("data-ohw-footer-column") || isFooterLinksContainer(el) || isInferredFooterGroup2(el)) {
16474
+ if (el.hasAttribute("data-ohw-nav-container") || el.hasAttribute("data-ohw-nav-drawer") || isFooterLinksContainer(el)) {
16631
16475
  return getNavigationRoot(el);
16632
16476
  }
16633
16477
  return null;
@@ -16843,6 +16687,7 @@ var ICONS = {
16843
16687
  insertUnorderedList: '<line x1="8" y1="6" x2="21" y2="6"/><line x1="8" y1="12" x2="21" y2="12"/><line x1="8" y1="18" x2="21" y2="18"/><line x1="3" y1="6" x2="3.01" y2="6"/><line x1="3" y1="12" x2="3.01" y2="12"/><line x1="3" y1="18" x2="3.01" y2="18"/>',
16844
16688
  insertOrderedList: '<line x1="10" y1="6" x2="21" y2="6"/><line x1="10" y1="12" x2="21" y2="12"/><line x1="10" y1="18" x2="21" y2="18"/><path d="M4 6h1v4"/><path d="M4 10h2"/><path d="M6 18H4c0-1 2-2 2-3s-1-1.5-2-1"/>'
16845
16689
  };
16690
+ var HEIGHT_SETTLE_DELAYS = [150, 400, 800];
16846
16691
  var SELECTION_CHROME_GAP2 = 4;
16847
16692
  var TOOLBAR_STROKE_GAP2 = 4;
16848
16693
  var TOOLBAR_OFFSET_FROM_ELEMENT = SELECTION_CHROME_GAP2 + TOOLBAR_STROKE_GAP2;
@@ -16939,10 +16784,6 @@ function getIframeVisibleClip(parentScroll) {
16939
16784
  );
16940
16785
  return { top: clipTop, bottom: Math.max(clipTop, clipBottom) };
16941
16786
  }
16942
- function isRectOutsideClip(rect, clip) {
16943
- if (!clip) return false;
16944
- return rect.bottom < clip.top || rect.top > clip.bottom;
16945
- }
16946
16787
  function applyVisibleViewport(el, parentScroll) {
16947
16788
  const clip = getIframeVisibleClip(parentScroll);
16948
16789
  const top = clip?.top ?? 0;
@@ -17226,7 +17067,6 @@ function StateToggle({
17226
17067
  );
17227
17068
  }
17228
17069
  var contentCache = /* @__PURE__ */ new Map();
17229
- var fetchedContentPaths = /* @__PURE__ */ new Set();
17230
17070
  var brandingCache = /* @__PURE__ */ new Map();
17231
17071
  var OHW_LOADER_STYLE = {
17232
17072
  position: "fixed",
@@ -17775,6 +17615,13 @@ function OhhwellsBridge() {
17775
17615
  const [isItemDragging, setIsItemDragging] = (0, import_react17.useState)(false);
17776
17616
  const [isFooterFrameSelection, setIsFooterFrameSelection] = (0, import_react17.useState)(false);
17777
17617
  isFooterFrameSelectionRef.current = isFooterFrameSelection;
17618
+ const [floatingPanel, setFloatingPanel] = (0, import_react17.useState)(null);
17619
+ const floatingPanelOpenRef = (0, import_react17.useRef)(false);
17620
+ floatingPanelOpenRef.current = floatingPanel !== null;
17621
+ const [floatingPanelPos, setFloatingPanelPos] = (0, import_react17.useState)(null);
17622
+ const [logoSizeDraft, setLogoSizeDraft] = (0, import_react17.useState)(null);
17623
+ const [editorViewport, setEditorViewport] = (0, import_react17.useState)("desktop");
17624
+ const [parentScrollSnap, setParentScrollSnap] = (0, import_react17.useState)(null);
17778
17625
  const [navDropdownPreviewOpen, setNavDropdownPreviewOpen] = (0, import_react17.useState)(null);
17779
17626
  const [footerHeadingVisible, setFooterHeadingVisible] = (0, import_react17.useState)(null);
17780
17627
  const footerDragRef = (0, import_react17.useRef)(null);
@@ -17792,13 +17639,6 @@ function OhhwellsBridge() {
17792
17639
  const brandKitRef = (0, import_react17.useRef)("");
17793
17640
  const stylesRef = (0, import_react17.useRef)("");
17794
17641
  const pendingDeleteUndoRef = (0, import_react17.useRef)(null);
17795
- const [floatingPanel, setFloatingPanel] = (0, import_react17.useState)(null);
17796
- const floatingPanelOpenRef = (0, import_react17.useRef)(false);
17797
- const setFloatingPanelRef = (0, import_react17.useRef)(setFloatingPanel);
17798
- const [floatingPanelPos, setFloatingPanelPos] = (0, import_react17.useState)(null);
17799
- const [logoSizeDraft, setLogoSizeDraft] = (0, import_react17.useState)(null);
17800
- const [editorViewport, setEditorViewport] = (0, import_react17.useState)("desktop");
17801
- const [parentScrollSnap, setParentScrollSnap] = (0, import_react17.useState)(null);
17802
17642
  const [sitePages, setSitePages] = (0, import_react17.useState)([]);
17803
17643
  const [sectionsByPath, setSectionsByPath] = (0, import_react17.useState)({});
17804
17644
  const sectionsPrefetchGenRef = (0, import_react17.useRef)(0);
@@ -17807,18 +17647,7 @@ function OhhwellsBridge() {
17807
17647
  const linkPopoverOpenRef = (0, import_react17.useRef)(false);
17808
17648
  const linkPopoverGraceUntilRef = (0, import_react17.useRef)(0);
17809
17649
  setLinkPopoverRef.current = setLinkPopover;
17810
- setFloatingPanelRef.current = setFloatingPanel;
17811
17650
  linkPopoverSessionRef.current = linkPopover;
17812
- floatingPanelOpenRef.current = Boolean(floatingPanel);
17813
- (0, import_react17.useEffect)(() => {
17814
- const syncViewport = () => {
17815
- const next = window.innerWidth <= 480 ? "mobile" : "desktop";
17816
- setEditorViewport((prev) => prev === next ? prev : next);
17817
- };
17818
- syncViewport();
17819
- window.addEventListener("resize", syncViewport);
17820
- return () => window.removeEventListener("resize", syncViewport);
17821
- }, []);
17822
17651
  const {
17823
17652
  navDragRef,
17824
17653
  navPointerDragRef,
@@ -19159,7 +18988,6 @@ function OhhwellsBridge() {
19159
18988
  }
19160
18989
  if (typeof content[STYLE_STORE_KEY] === "string") {
19161
18990
  stylesRef.current = content[STYLE_STORE_KEY];
19162
- document.querySelectorAll('[data-ohw-editable="form"]').forEach((f) => markFormFields(f));
19163
18991
  applyStylesToDom(parseStyleStore(content[STYLE_STORE_KEY]));
19164
18992
  }
19165
18993
  applyBrandChrome(content);
@@ -19167,11 +18995,11 @@ function OhhwellsBridge() {
19167
18995
  for (const [key, val] of Object.entries(content)) {
19168
18996
  if (key === "__ohw_sections") continue;
19169
18997
  if (key === AI_SECTIONS_KEY) continue;
19170
- if (key === LOGO_PLACEHOLDER_KEY) continue;
19171
- if (LOGO_IMAGE_KEYS.includes(key)) continue;
19172
18998
  if (key === BRAND_KIT_KEY) continue;
19173
18999
  if (key === STYLE_STORE_KEY) continue;
19174
19000
  if (BRAND_CHROME_KEYS.has(key)) continue;
19001
+ if (key === LOGO_PLACEHOLDER_KEY) continue;
19002
+ if (LOGO_IMAGE_KEYS.includes(key)) continue;
19175
19003
  if (applyVideoSettingNode(key, val)) continue;
19176
19004
  if (applyCarouselNode(key, val)) continue;
19177
19005
  document.querySelectorAll(`[data-ohw-key="${key}"]`).forEach((el) => {
@@ -19242,9 +19070,7 @@ function OhhwellsBridge() {
19242
19070
  let cancelled = false;
19243
19071
  setFetchState("loading");
19244
19072
  const apiUrl = process.env.NEXT_PUBLIC_FLOWOPS_API_URL ?? "https://flowops-backend-staging-2yfdh7pwpq-as.a.run.app";
19245
- const initialPath = pathname;
19246
- fetchedContentPaths.add(`${subdomain}::${initialPath}`);
19247
- fetch(`${apiUrl}/api/public/sites/${subdomain}/content?path=${encodeURIComponent(initialPath)}`, { cache: "no-store" }).then((r2) => r2.ok ? r2.json() : null).then((data) => {
19073
+ fetch(`${apiUrl}/api/public/sites/${subdomain}/content`, { cache: "no-store" }).then((r2) => r2.ok ? r2.json() : null).then((data) => {
19248
19074
  if (cancelled) return;
19249
19075
  const content = data?.content ?? {};
19250
19076
  const branding = Boolean(data?.showBranding);
@@ -19353,9 +19179,7 @@ function OhhwellsBridge() {
19353
19179
  }, [isEditMode]);
19354
19180
  (0, import_react17.useEffect)(() => {
19355
19181
  if (isEditMode || fetchState !== "done") return;
19356
- console.log("env", process.env.NEXT_PUBLIC_FLOWOPS_API_URL);
19357
19182
  const apiUrl = process.env.NEXT_PUBLIC_FLOWOPS_API_URL ?? "https://flowops-backend-staging-2yfdh7pwpq-as.a.run.app";
19358
- console.log({ apiUrl, subdomain });
19359
19183
  bindPublishedForms(apiUrl, subdomain, contentCache.get(subdomain) ?? {});
19360
19184
  }, [isEditMode, fetchState, subdomain]);
19361
19185
  (0, import_react17.useEffect)(() => {
@@ -19380,17 +19204,16 @@ function OhhwellsBridge() {
19380
19204
  applyAiSectionsToDom(parseAiSectionsState(content[AI_SECTIONS_KEY]));
19381
19205
  }
19382
19206
  if (typeof content[STYLE_STORE_KEY] === "string") {
19383
- document.querySelectorAll('[data-ohw-editable="form"]').forEach((f) => markFormFields(f));
19384
19207
  applyStylesToDom(parseStyleStore(content[STYLE_STORE_KEY]));
19385
19208
  }
19386
19209
  for (const [key, val] of Object.entries(content)) {
19387
19210
  if (key === "__ohw_sections") continue;
19388
19211
  if (key === AI_SECTIONS_KEY) continue;
19389
- if (key === LOGO_PLACEHOLDER_KEY) continue;
19390
- if (LOGO_IMAGE_KEYS.includes(key)) continue;
19391
19212
  if (key === BRAND_KIT_KEY) continue;
19392
19213
  if (key === STYLE_STORE_KEY) continue;
19393
19214
  if (BRAND_CHROME_KEYS.has(key)) continue;
19215
+ if (key === LOGO_PLACEHOLDER_KEY) continue;
19216
+ if (LOGO_IMAGE_KEYS.includes(key)) continue;
19394
19217
  if (applyVideoSettingNode(key, val)) continue;
19395
19218
  if (applyCarouselNode(key, val)) continue;
19396
19219
  document.querySelectorAll(`[data-ohw-key="${key}"]`).forEach((el) => {
@@ -19441,17 +19264,6 @@ function OhhwellsBridge() {
19441
19264
  debounceTimer = setTimeout(applyFromCache, 150);
19442
19265
  };
19443
19266
  applyFromCache();
19444
- const pathCacheKey = `${subdomain}::${pathname}`;
19445
- if (!fetchedContentPaths.has(pathCacheKey)) {
19446
- fetchedContentPaths.add(pathCacheKey);
19447
- const apiUrl = process.env.NEXT_PUBLIC_FLOWOPS_API_URL ?? "https://flowops-backend-staging-2yfdh7pwpq-as.a.run.app";
19448
- fetch(`${apiUrl}/api/public/sites/${subdomain}/content?path=${encodeURIComponent(pathname)}`, { cache: "no-store" }).then((r2) => r2.ok ? r2.json() : null).then((data) => {
19449
- if (!data?.content) return;
19450
- contentCache.set(subdomain, data.content);
19451
- applyFromCache();
19452
- }).catch(() => {
19453
- });
19454
- }
19455
19267
  observer = new MutationObserver(scheduleApply);
19456
19268
  observer.observe(document.body, { childList: true, subtree: true });
19457
19269
  return () => {
@@ -19587,11 +19399,26 @@ function OhhwellsBridge() {
19587
19399
  const t2 = setTimeout(measure, 500);
19588
19400
  const ro = new ResizeObserver(schedule);
19589
19401
  ro.observe(document.body);
19402
+ let lastWidth = window.innerWidth;
19403
+ let resizeTimers = [];
19404
+ const clearResizeTimers = () => {
19405
+ resizeTimers.forEach(clearTimeout);
19406
+ resizeTimers = [];
19407
+ };
19408
+ const handleResize = () => {
19409
+ if (window.innerWidth === lastWidth) return;
19410
+ lastWidth = window.innerWidth;
19411
+ clearResizeTimers();
19412
+ resizeTimers = HEIGHT_SETTLE_DELAYS.map((delay) => setTimeout(measure, delay));
19413
+ };
19414
+ window.addEventListener("resize", handleResize);
19590
19415
  return () => {
19591
19416
  clearTimeout(t1);
19592
19417
  clearTimeout(t2);
19593
19418
  if (raf != null) cancelAnimationFrame(raf);
19594
19419
  ro.disconnect();
19420
+ clearResizeTimers();
19421
+ window.removeEventListener("resize", handleResize);
19595
19422
  };
19596
19423
  }, [pathname, isEditMode, postToParent2]);
19597
19424
  (0, import_react17.useEffect)(() => {
@@ -19864,6 +19691,9 @@ function OhhwellsBridge() {
19864
19691
  if (target.closest("[data-ohw-state-toggle]")) return;
19865
19692
  if (target.closest("[data-ohw-max-badge]")) return;
19866
19693
  if (isInsideLinkEditor(target)) return;
19694
+ if (selectedMediaElRef.current && !selectedMediaElRef.current.contains(target) && !target.closest("[data-ohw-media-overlay], [data-ohw-edit-chrome], [data-ohw-item-interaction]")) {
19695
+ clearMediaSelectionRef.current();
19696
+ }
19867
19697
  if (isInsideFloatingPanel(target)) return;
19868
19698
  if (target.closest("[data-ohw-form-toolbar]")) return;
19869
19699
  if (target.closest(
@@ -19871,9 +19701,6 @@ function OhhwellsBridge() {
19871
19701
  )) {
19872
19702
  return;
19873
19703
  }
19874
- if (selectedMediaElRef.current && !selectedMediaElRef.current.contains(target) && !target.closest("[data-ohw-media-overlay], [data-ohw-edit-chrome], [data-ohw-item-interaction]")) {
19875
- clearMediaSelectionRef.current();
19876
- }
19877
19704
  {
19878
19705
  const formEl = getFormElement(target);
19879
19706
  const onSuccessText = target.closest(`[${SUCCESS_TEXT_ATTR}]`);
@@ -20037,6 +19864,14 @@ function OhhwellsBridge() {
20037
19864
  }
20038
19865
  const clickedButton = findClosestButtonLike(target);
20039
19866
  const buttonOnMedia = Boolean(clickedButton && isMediaEditable(editable) && editable.contains(clickedButton));
19867
+ console.log("[click-debug]", {
19868
+ editableType: editable.dataset.ohwEditable,
19869
+ editableTag: editable.tagName,
19870
+ targetTag: target.tagName,
19871
+ clickedButtonTag: clickedButton?.tagName ?? null,
19872
+ buttonOnMedia,
19873
+ isMediaEditableEditable: isMediaEditable(editable)
19874
+ });
20040
19875
  if (isMediaEditable(editable) && !buttonOnMedia) {
20041
19876
  e.preventDefault();
20042
19877
  e.stopPropagation();
@@ -20063,6 +19898,11 @@ function OhhwellsBridge() {
20063
19898
  const hrefLookupTarget = buttonOnMedia ? clickedButton : editable;
20064
19899
  const hrefCtx = getHrefKeyFromElement(hrefLookupTarget);
20065
19900
  const navAnchor = hrefCtx ? getNavigationItemAnchor(hrefCtx.anchor) : null;
19901
+ console.log("[click-debug 2]", {
19902
+ hrefLookupTargetTag: hrefLookupTarget.tagName,
19903
+ hrefCtx: hrefCtx ? { key: hrefCtx.key } : null,
19904
+ navAnchorTag: navAnchor?.tagName ?? null
19905
+ });
20066
19906
  if (navAnchor) {
20067
19907
  e.preventDefault();
20068
19908
  e.stopPropagation();
@@ -20232,9 +20072,6 @@ function OhhwellsBridge() {
20232
20072
  setHoveredItemRect(null);
20233
20073
  hoveredNavContainerRef.current = null;
20234
20074
  setHoveredNavContainerRect(null);
20235
- siblingHintElRef.current = null;
20236
- setSiblingHintRect(null);
20237
- setSiblingHintRects([]);
20238
20075
  return;
20239
20076
  }
20240
20077
  {
@@ -20355,6 +20192,7 @@ function OhhwellsBridge() {
20355
20192
  hoveredNavContainerRef.current = null;
20356
20193
  setHoveredNavContainerRect(null);
20357
20194
  hoveredItemElRef.current = editable;
20195
+ setHoveredItemRect(isSelectedForHoverRef.current(editable) ? null : editable.getBoundingClientRect());
20358
20196
  }
20359
20197
  }
20360
20198
  }
@@ -20651,7 +20489,7 @@ function OhhwellsBridge() {
20651
20489
  }
20652
20490
  };
20653
20491
  const probeImageAt = (clientX, clientY, isDragOver = false, fromParentViewport = false) => {
20654
- if (linkPopoverOpenRef.current || floatingPanelOpenRef.current && isPointOverFloatingPanel(clientX, clientY)) {
20492
+ if (linkPopoverOpenRef.current) {
20655
20493
  if (hoveredImageRef.current) {
20656
20494
  hoveredImageRef.current = null;
20657
20495
  hoveredImageHasTextOverlapRef.current = false;
@@ -21024,7 +20862,8 @@ function OhhwellsBridge() {
21024
20862
  };
21025
20863
  const handleMouseMove = (e) => {
21026
20864
  const { clientX, clientY } = e;
21027
- if (document.documentElement.hasAttribute("data-ohw-panel-dragging") || floatingPanelOpenRef.current && isPointOverFloatingPanel(clientX, clientY) || isOverEditorChrome(clientX, clientY)) {
20865
+ if (pointOwnedByFloatingPanel(clientX, clientY)) return;
20866
+ if (isOverEditorChrome(clientX, clientY)) {
21028
20867
  document.querySelectorAll("[data-ohw-hovered]").forEach((el) => el.removeAttribute("data-ohw-hovered"));
21029
20868
  formHoverElRef.current = null;
21030
20869
  setFormHoverRect(null);
@@ -21032,12 +20871,6 @@ function OhhwellsBridge() {
21032
20871
  setHoveredItemRect(null);
21033
20872
  hoveredNavContainerRef.current = null;
21034
20873
  setHoveredNavContainerRect(null);
21035
- siblingHintElRef.current = null;
21036
- setSiblingHintRect(null);
21037
- setSiblingHintRects([]);
21038
- dismissImageHover();
21039
- clearImageHover();
21040
- setSectionGap(null);
21041
20874
  return;
21042
20875
  }
21043
20876
  if (probeSocialsRowAt(clientX, clientY)) return;
@@ -21049,11 +20882,7 @@ function OhhwellsBridge() {
21049
20882
  if (e.data?.type !== "ow:pointer-sync") return;
21050
20883
  const { clientX, clientY } = e.data;
21051
20884
  if (typeof clientX !== "number" || typeof clientY !== "number") return;
21052
- if (document.documentElement.hasAttribute("data-ohw-panel-dragging") || floatingPanelOpenRef.current && isPointOverFloatingPanel(clientX, clientY)) {
21053
- dismissImageHover();
21054
- clearImageHover();
21055
- return;
21056
- }
20885
+ if (pointOwnedByFloatingPanel(clientX, clientY)) return;
21057
20886
  if (probeSocialsRowAt(clientX, clientY)) return;
21058
20887
  probeSectionGapAt(clientX, clientY);
21059
20888
  probeImageAt(clientX, clientY);
@@ -21392,7 +21221,6 @@ function OhhwellsBridge() {
21392
21221
  }
21393
21222
  if (typeof content[STYLE_STORE_KEY] === "string") {
21394
21223
  stylesRef.current = content[STYLE_STORE_KEY];
21395
- document.querySelectorAll('[data-ohw-editable="form"]').forEach((f) => markFormFields(f));
21396
21224
  applyStylesToDom(parseStyleStore(content[STYLE_STORE_KEY]));
21397
21225
  }
21398
21226
  applyBrandChrome(content);
@@ -21404,11 +21232,11 @@ function OhhwellsBridge() {
21404
21232
  continue;
21405
21233
  }
21406
21234
  if (key === AI_SECTIONS_KEY) continue;
21407
- if (key === LOGO_PLACEHOLDER_KEY) continue;
21408
- if (LOGO_IMAGE_KEYS.includes(key) && !String(val ?? "").trim()) continue;
21409
21235
  if (key === BRAND_KIT_KEY) continue;
21410
21236
  if (key === STYLE_STORE_KEY) continue;
21411
21237
  if (BRAND_CHROME_KEYS.has(key)) continue;
21238
+ if (key === LOGO_PLACEHOLDER_KEY) continue;
21239
+ if (LOGO_IMAGE_KEYS.includes(key) && !String(val ?? "").trim()) continue;
21412
21240
  if (applyVideoSettingNode(key, val)) continue;
21413
21241
  if (applyCarouselNode(key, val)) continue;
21414
21242
  document.querySelectorAll(`[data-ohw-key="${key}"]`).forEach((el) => {
@@ -21629,26 +21457,10 @@ function OhhwellsBridge() {
21629
21457
  const handleGetBrand = (e) => {
21630
21458
  if (e.data?.type !== "ow:get-brand") return;
21631
21459
  const template = deriveTemplateBrand();
21632
- const fallback = template ?? (() => {
21633
- const fonts = deriveTemplateFonts();
21634
- return fonts ? { palette: AI_DEFAULT_BRAND.palette, fonts } : null;
21635
- })();
21636
- const value = brandKitRef.current || (fallback ? JSON.stringify(fallback) : "");
21460
+ const value = brandKitRef.current || (template ? JSON.stringify(template) : "");
21637
21461
  postToParentRef.current({ type: "ow:brand-value", value });
21638
21462
  };
21639
21463
  window.addEventListener("message", handleGetBrand);
21640
- const handleGetTemplateFonts = (e) => {
21641
- if (e.data?.type !== "ow:get-template-fonts") return;
21642
- const fonts = deriveTemplateFonts();
21643
- postToParentRef.current({ type: "ow:template-fonts-value", value: fonts ? JSON.stringify(fonts) : "" });
21644
- };
21645
- window.addEventListener("message", handleGetTemplateFonts);
21646
- const handleGetTemplateBrand = (e) => {
21647
- if (e.data?.type !== "ow:get-template-brand") return;
21648
- const brand = deriveTemplateBrand();
21649
- postToParentRef.current({ type: "ow:template-brand-value", value: brand ? JSON.stringify(brand) : "" });
21650
- };
21651
- window.addEventListener("message", handleGetTemplateBrand);
21652
21464
  const handleMoveSection = (e) => {
21653
21465
  if (e.data?.type !== "ow:move-section") return;
21654
21466
  const instanceId = typeof e.data.instanceId === "string" ? e.data.instanceId : "";
@@ -21841,12 +21653,6 @@ function OhhwellsBridge() {
21841
21653
  closeLinkPopoverRef.current();
21842
21654
  return;
21843
21655
  }
21844
- if (floatingPanelOpenRef.current) {
21845
- setFloatingPanelRef.current(null);
21846
- deselectRef.current();
21847
- deactivateRef.current();
21848
- return;
21849
- }
21850
21656
  deselectRef.current();
21851
21657
  deactivateRef.current();
21852
21658
  clearMediaSelectionRef.current();
@@ -22135,12 +21941,8 @@ function OhhwellsBridge() {
22135
21941
  if (inserted) {
22136
21942
  const tracker = getSectionsTracker();
22137
21943
  postToParentRef.current({ type: "ow:change", nodes: [{ key: "__ohw_sections", text: tracker.textContent ?? "[]" }] });
22138
- const reportHeight = () => {
22139
- const h = document.body.scrollHeight;
22140
- if (h > 50) postToParentRef.current({ type: "ow:height", height: h });
22141
- };
22142
- reportHeight();
22143
- setTimeout(reportHeight, 500);
21944
+ const h = document.body.scrollHeight;
21945
+ if (h > 50) postToParentRef.current({ type: "ow:height", height: h });
22144
21946
  }
22145
21947
  };
22146
21948
  const handleSwitchSchedule = (e) => {
@@ -22317,20 +22119,14 @@ function OhhwellsBridge() {
22317
22119
  };
22318
22120
  const applyToolbarPos = (rect) => {
22319
22121
  const ps = parentScrollRef.current;
22320
- const hidden = isRectOutsideClip(rect, getIframeVisibleClip(ps));
22321
22122
  const measuredW = toolbarElRef.current?.offsetWidth || 330;
22322
22123
  if (toolbarElRef.current) {
22323
- toolbarElRef.current.style.display = hidden ? "none" : "";
22324
- if (!hidden) {
22325
- const { top, left, transform } = calcToolbarPos(rect, ps, measuredW);
22326
- toolbarElRef.current.style.top = `${top}px`;
22327
- toolbarElRef.current.style.left = `${left}px`;
22328
- toolbarElRef.current.style.transform = transform;
22329
- }
22124
+ const { top, left, transform } = calcToolbarPos(rect, ps, measuredW);
22125
+ toolbarElRef.current.style.top = `${top}px`;
22126
+ toolbarElRef.current.style.left = `${left}px`;
22127
+ toolbarElRef.current.style.transform = transform;
22330
22128
  }
22331
22129
  if (glowElRef.current) {
22332
- glowElRef.current.style.display = hidden ? "none" : "";
22333
- if (hidden) return;
22334
22130
  const GAP = SELECTION_CHROME_GAP2;
22335
22131
  glowElRef.current.style.top = `${rect.top - GAP}px`;
22336
22132
  glowElRef.current.style.left = `${rect.left - GAP}px`;
@@ -22561,17 +22357,15 @@ function OhhwellsBridge() {
22561
22357
  window.removeEventListener("message", handleAiSetBrand);
22562
22358
  window.removeEventListener("message", handleAiSetStyles);
22563
22359
  window.removeEventListener("message", handleGetBrand);
22564
- window.removeEventListener("message", handleGetTemplateFonts);
22565
- window.removeEventListener("message", handleGetTemplateBrand);
22566
22360
  window.removeEventListener("message", handleMoveSection);
22567
22361
  window.removeEventListener("message", handlePanelDragging);
22568
22362
  window.removeEventListener("message", handleDeleteSection);
22569
22363
  window.removeEventListener("message", handleDuplicateSection);
22570
22364
  window.removeEventListener("message", handleDeactivate);
22365
+ document.documentElement.removeAttribute("data-ohw-panel-dragging");
22571
22366
  window.removeEventListener("message", handleToastAction);
22572
22367
  window.removeEventListener("message", handleFormCount);
22573
22368
  window.removeEventListener("message", handleUiEscape);
22574
- document.documentElement.removeAttribute("data-ohw-panel-dragging");
22575
22369
  autoSaveTimers.current.forEach(clearTimeout);
22576
22370
  autoSaveTimers.current.clear();
22577
22371
  if (imageUnhoverTimerRef.current) clearTimeout(imageUnhoverTimerRef.current);
@@ -22774,7 +22568,7 @@ function OhhwellsBridge() {
22774
22568
  postToParent2({
22775
22569
  type: "ow:ready",
22776
22570
  version: "1",
22777
- bridgeVersion: "0.1.108",
22571
+ bridgeVersion: "0.1.107",
22778
22572
  path: pathname,
22779
22573
  nodes: collectEditableNodes(editContentRef.current),
22780
22574
  sections
@@ -23390,7 +23184,7 @@ function OhhwellsBridge() {
23390
23184
  "span",
23391
23185
  {
23392
23186
  "data-ohw-form-count": "",
23393
- className: "ml-0.5 inline-flex h-[18px] min-w-[18px] items-center justify-center rounded-full bg-bridge-primary px-1.5 text-[11px] font-semibold text-primary-foreground",
23187
+ className: "ml-0.5 inline-flex h-[18px] min-w-[18px] items-center justify-center rounded-full bg-primary px-1.5 text-[11px] font-semibold text-primary-foreground",
23394
23188
  children: formPickCount
23395
23189
  }
23396
23190
  )
@@ -23561,7 +23355,7 @@ function OhhwellsBridge() {
23561
23355
  ) : void 0
23562
23356
  }
23563
23357
  ),
23564
- toolbarRect && toolbarVariant === "rich-text" && !linkPopover && !isRectOutsideClip(toolbarRect, getIframeVisibleClip(parentScrollRef.current)) && /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)(import_jsx_runtime33.Fragment, { children: [
23358
+ toolbarRect && toolbarVariant === "rich-text" && !linkPopover && /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)(import_jsx_runtime33.Fragment, { children: [
23565
23359
  /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
23566
23360
  EditGlowChrome,
23567
23361
  {
@@ -23627,11 +23421,11 @@ function OhhwellsBridge() {
23627
23421
  className: "fixed left-0 w-full z-2147483646 flex items-center pointer-events-none",
23628
23422
  style: { top: sectionGap.y, transform: "translateY(-50%)" },
23629
23423
  children: [
23630
- /* @__PURE__ */ (0, import_jsx_runtime33.jsx)("div", { className: "flex-1 bg-bridge-primary", style: { height: 3 } }),
23424
+ /* @__PURE__ */ (0, import_jsx_runtime33.jsx)("div", { className: "flex-1 bg-primary", style: { height: 3 } }),
23631
23425
  /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
23632
23426
  Badge,
23633
23427
  {
23634
- 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",
23428
+ className: "px-8 py-1 bg-primary hover:bg-primary text-primary-foreground text-xs font-medium shrink-0 rounded-full cursor-pointer pointer-events-auto",
23635
23429
  onClick: () => {
23636
23430
  window.parent.postMessage(
23637
23431
  {
@@ -23645,7 +23439,7 @@ function OhhwellsBridge() {
23645
23439
  children: "Add Section"
23646
23440
  }
23647
23441
  ),
23648
- /* @__PURE__ */ (0, import_jsx_runtime33.jsx)("div", { className: "flex-1 bg-bridge-primary", style: { height: 3 } })
23442
+ /* @__PURE__ */ (0, import_jsx_runtime33.jsx)("div", { className: "flex-1 bg-primary", style: { height: 3 } })
23649
23443
  ]
23650
23444
  }
23651
23445
  ),
@@ -23693,59 +23487,6 @@ function OhhwellsBridge() {
23693
23487
  ) : null
23694
23488
  ] });
23695
23489
  }
23696
-
23697
- // src/ui/EmptySection.tsx
23698
- var import_link = __toESM(require("next/link"), 1);
23699
- var import_jsx_runtime34 = require("react/jsx-runtime");
23700
- function EmptySection({ title, homeHref = "/", eyebrowKey, titleKey, subtitleKey }) {
23701
- return /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)(import_jsx_runtime34.Fragment, { children: [
23702
- /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
23703
- "p",
23704
- {
23705
- style: {
23706
- fontFamily: "var(--brand-font-body)",
23707
- fontSize: "0.75rem",
23708
- fontWeight: 500,
23709
- letterSpacing: "0.15em",
23710
- textTransform: "uppercase",
23711
- color: "var(--brand-accent)",
23712
- marginBottom: "1.5rem"
23713
- },
23714
- 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" }) })
23715
- }
23716
- ),
23717
- /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
23718
- "h1",
23719
- {
23720
- style: {
23721
- fontFamily: "var(--brand-font-heading)",
23722
- fontSize: "clamp(2rem, 3.5vw, 2.75rem)",
23723
- lineHeight: 1.1,
23724
- letterSpacing: "-0.025em",
23725
- color: "var(--brand-text)",
23726
- marginBottom: "1rem"
23727
- },
23728
- ...titleKey ? { "data-ohw-editable": "text", "data-ohw-key": titleKey, "data-ohw-max-length": 80 } : {},
23729
- children: title
23730
- }
23731
- ),
23732
- /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
23733
- "p",
23734
- {
23735
- style: {
23736
- fontFamily: "var(--brand-font-body)",
23737
- fontSize: "1rem",
23738
- lineHeight: 1.7,
23739
- fontWeight: 300,
23740
- color: "var(--brand-text-muted)",
23741
- maxWidth: "340px"
23742
- },
23743
- ...subtitleKey ? { "data-ohw-editable": "text", "data-ohw-key": subtitleKey, "data-ohw-max-length": 160 } : {},
23744
- children: "This page doesn't have any content yet."
23745
- }
23746
- )
23747
- ] });
23748
- }
23749
23490
  // Annotate the CommonJS export names for ESM import in node:
23750
23491
  0 && (module.exports = {
23751
23492
  AI_DEFAULT_BRAND,
@@ -23763,7 +23504,6 @@ function EmptySection({ title, homeHref = "/", eyebrowKey, titleKey, subtitleKey
23763
23504
  DropdownMenuItem,
23764
23505
  DropdownMenuSeparator,
23765
23506
  DropdownMenuTrigger,
23766
- EmptySection,
23767
23507
  ItemActionToolbar,
23768
23508
  ItemInteractionLayer,
23769
23509
  LinkEditorPanel,