@ohhwells/bridge 0.1.92-next.274 → 0.1.93-next.277

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
@@ -353,16 +353,17 @@ var LEGACY_BRAND_VAR_NAMES = [
353
353
  "text-muted",
354
354
  "surface",
355
355
  "border",
356
- "on-primary",
357
- "navbar-background"
356
+ "on-primary"
358
357
  ].map((role) => `--brand-${role}`);
359
358
  var FONT_VARS = {
360
359
  heading: ["--font-heading", "--font-display", "--brand-font-heading"],
361
360
  body: ["--font-body", "--brand-font-body"]
362
361
  };
363
362
  var BRAND_FONT_LINK_ID = "ohw-brand-fonts";
364
- function brandColorVars(kit) {
365
- const { dark, primary, accent, light } = kit.palette;
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;
366
367
  const mix = (a, aPct, b) => `color-mix(in srgb, ${a} ${aPct}%, ${b})`;
367
368
  const surface = mix(light, 95, dark);
368
369
  const border = mix(light, 85, dark);
@@ -385,22 +386,42 @@ function brandColorVars(kit) {
385
386
  "--brand-border": border,
386
387
  // Buttons/bands painted in the primary colour assume it's dark/saturated enough to need
387
388
  // light text on top — the same assumption LOGO_IMAGE's light-on-dark navbar mark makes.
388
- "--brand-on-primary": light,
389
- "--brand-navbar-background": dark
389
+ "--brand-on-primary": light
390
390
  };
391
391
  }
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
+ }
392
411
  function parseBrandKit(raw) {
393
412
  if (!raw) return null;
394
413
  try {
395
414
  const parsed = JSON.parse(raw);
396
415
  const p = parsed?.palette;
397
416
  const f = parsed?.fonts;
398
- 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") {
399
- return null;
400
- }
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;
401
421
  return {
402
- palette: { dark: p.dark, primary: p.primary, accent: p.accent, light: p.light },
403
- fonts: { heading: f.heading, body: f.body }
422
+ ...palette ? { palette } : {},
423
+ ...fonts ? { fonts } : {},
424
+ ...customFonts ? { customFonts } : {}
404
425
  };
405
426
  } catch {
406
427
  return null;
@@ -410,11 +431,16 @@ function familyOf(stack) {
410
431
  const first = stack.split(",")[0]?.trim() ?? "";
411
432
  return first.replace(/^['"]|['"]$/g, "");
412
433
  }
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];
413
438
  function loadBrandFonts(families) {
414
439
  const unique = [...new Set(families.map((f) => f.trim()).filter(Boolean))];
415
440
  if (unique.length === 0) return;
416
- const spec = unique.map((f) => `${f.replace(/ /g, "+")}:400,500,600,700`).join("|");
417
- const href = `https://fonts.googleapis.com/css?family=${spec}&display=swap`;
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`;
418
444
  let link = document.getElementById(BRAND_FONT_LINK_ID);
419
445
  if (!link) {
420
446
  link = document.createElement("link");
@@ -424,18 +450,54 @@ function loadBrandFonts(families) {
424
450
  }
425
451
  if (link.href !== href) link.href = href;
426
452
  }
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
+ }
427
475
  function applyBrandToDom(kit) {
428
476
  const root = document.documentElement;
429
477
  if (!kit) {
430
478
  for (const name of [...BRAND_VAR_NAMES, ...LEGACY_BRAND_VAR_NAMES]) root.style.removeProperty(name);
431
479
  for (const name of [...FONT_VARS.heading, ...FONT_VARS.body]) root.style.removeProperty(name);
432
480
  document.getElementById(BRAND_FONT_LINK_ID)?.remove();
481
+ document.getElementById(CUSTOM_FONT_STYLE_ID)?.remove();
433
482
  return;
434
483
  }
435
- for (const [name, value] of Object.entries(brandColorVars(kit))) root.style.setProperty(name, value);
436
- for (const name of FONT_VARS.heading) root.style.setProperty(name, kit.fonts.heading);
437
- for (const name of FONT_VARS.body) root.style.setProperty(name, kit.fonts.body);
438
- loadBrandFonts([familyOf(kit.fonts.heading), familyOf(kit.fonts.body)]);
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
+ }
439
501
  }
440
502
 
441
503
  // src/lib/section-styles.ts
@@ -2657,14 +2719,52 @@ function readRootVar(name) {
2657
2719
  if (typeof document === "undefined") return "";
2658
2720
  return getComputedStyle(document.documentElement).getPropertyValue(name).trim();
2659
2721
  }
2722
+ function normalizeColorToHex(value) {
2723
+ if (!value || typeof document === "undefined") return value;
2724
+ const canvas = document.createElement("canvas");
2725
+ canvas.width = 1;
2726
+ canvas.height = 1;
2727
+ const ctx = canvas.getContext("2d");
2728
+ if (!ctx) return value;
2729
+ ctx.fillStyle = value;
2730
+ ctx.fillRect(0, 0, 1, 1);
2731
+ const [r2, g, b] = ctx.getImageData(0, 0, 1, 1).data;
2732
+ const toHex = (n) => n.toString(16).padStart(2, "0");
2733
+ return `#${toHex(r2)}${toHex(g)}${toHex(b)}`;
2734
+ }
2735
+ var GENERIC_FONT_KEYWORDS = /* @__PURE__ */ new Set([
2736
+ "serif",
2737
+ "sans-serif",
2738
+ "monospace",
2739
+ "cursive",
2740
+ "fantasy",
2741
+ "system-ui",
2742
+ "ui-serif",
2743
+ "ui-sans-serif",
2744
+ "ui-monospace",
2745
+ "ui-rounded",
2746
+ "math",
2747
+ "emoji",
2748
+ "fangsong"
2749
+ ]);
2750
+ function primaryFontFamily(stack) {
2751
+ const first = stack.split(",").map((part) => part.trim().replace(/^["']|["']$/g, "")).find((part) => part && !GENERIC_FONT_KEYWORDS.has(part.toLowerCase()));
2752
+ return first ?? "";
2753
+ }
2754
+ function humanizeFontFamily(name) {
2755
+ 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());
2756
+ }
2757
+ function readFontVar(name) {
2758
+ return humanizeFontFamily(primaryFontFamily(readRootVar(name)));
2759
+ }
2660
2760
  function deriveBrandOverride() {
2661
2761
  const dark = readRootVar("--ohw-brand-dark");
2662
2762
  const primary = readRootVar("--ohw-brand-primary");
2663
2763
  const light = readRootVar("--ohw-brand-light");
2664
2764
  if (!dark || !primary || !light) return null;
2665
2765
  const accent = readRootVar("--ohw-brand-accent");
2666
- const heading = readRootVar("--font-heading") || readRootVar("--font-display");
2667
- const body = readRootVar("--font-body");
2766
+ const heading = readFontVar("--font-heading") || readFontVar("--font-display");
2767
+ const body = readFontVar("--font-body");
2668
2768
  return {
2669
2769
  palette: { dark, primary, accent: accent || dark, light },
2670
2770
  fonts: {
@@ -2673,22 +2773,55 @@ function deriveBrandOverride() {
2673
2773
  }
2674
2774
  };
2675
2775
  }
2676
- function deriveTemplateBrand() {
2677
- const primary = readRootVar("--brand-primary") || readRootVar("--color-primary");
2678
- const dark = readRootVar("--brand-text") || readRootVar("--color-dark");
2679
- const light = readRootVar("--brand-background") || readRootVar("--color-light");
2776
+ function deriveTemplateBrandLive() {
2777
+ const dark = readRootVar("--color-dark") || readRootVar("--brand-text");
2778
+ const primary = readRootVar("--color-primary") || readRootVar("--brand-primary");
2779
+ const light = readRootVar("--color-light") || readRootVar("--brand-background");
2680
2780
  if (!dark || !primary || !light) return null;
2681
- const accent = readRootVar("--brand-accent") || readRootVar("--color-accent");
2682
- const heading = readRootVar("--brand-font-heading") || readRootVar("--font-heading") || readRootVar("--font-display");
2683
- const body = readRootVar("--brand-font-body") || readRootVar("--font-body");
2781
+ const accent = readRootVar("--color-accent") || readRootVar("--brand-accent");
2782
+ const heading = readFontVar("--brand-font-heading") || readFontVar("--font-heading") || readFontVar("--font-display");
2783
+ const body = readFontVar("--brand-font-body") || readFontVar("--font-body");
2684
2784
  return {
2685
- palette: { dark, primary, accent: accent || dark, light },
2785
+ palette: {
2786
+ dark: normalizeColorToHex(dark),
2787
+ primary: normalizeColorToHex(primary),
2788
+ accent: normalizeColorToHex(accent || dark),
2789
+ light: normalizeColorToHex(light)
2790
+ },
2686
2791
  fonts: {
2687
2792
  heading: heading || AI_DEFAULT_BRAND.fonts.heading,
2688
2793
  body: body || AI_DEFAULT_BRAND.fonts.body
2689
2794
  }
2690
2795
  };
2691
2796
  }
2797
+ function deriveTemplateFontsLive() {
2798
+ const heading = readFontVar("--brand-font-heading") || readFontVar("--font-heading") || readFontVar("--font-display");
2799
+ const body = readFontVar("--brand-font-body") || readFontVar("--font-body");
2800
+ if (!heading && !body) return null;
2801
+ return {
2802
+ heading: heading || AI_DEFAULT_BRAND.fonts.heading,
2803
+ body: body || AI_DEFAULT_BRAND.fonts.body
2804
+ };
2805
+ }
2806
+ var OVERRIDE_VAR_NAMES = [...BRAND_VAR_NAMES, ...LEGACY_BRAND_VAR_NAMES, ...FONT_VARS.heading, ...FONT_VARS.body];
2807
+ function withOverrideStripped(read) {
2808
+ const root = document.documentElement;
2809
+ const restore = OVERRIDE_VAR_NAMES.map((name) => [name, root.style.getPropertyValue(name)]);
2810
+ for (const name of OVERRIDE_VAR_NAMES) root.style.removeProperty(name);
2811
+ try {
2812
+ return read();
2813
+ } finally {
2814
+ for (const [name, value] of restore) if (value) root.style.setProperty(name, value);
2815
+ }
2816
+ }
2817
+ var TEMPLATE_BRAND_SNAPSHOT = typeof document === "undefined" ? null : withOverrideStripped(deriveTemplateBrandLive);
2818
+ var TEMPLATE_FONTS_SNAPSHOT = typeof document === "undefined" ? null : withOverrideStripped(deriveTemplateFontsLive);
2819
+ function deriveTemplateBrand() {
2820
+ return TEMPLATE_BRAND_SNAPSHOT;
2821
+ }
2822
+ function deriveTemplateFonts() {
2823
+ return TEMPLATE_FONTS_SNAPSHOT;
2824
+ }
2692
2825
  function deriveTemplateButtonStyle() {
2693
2826
  if (typeof document === "undefined") return null;
2694
2827
  const candidates = Array.from(
@@ -7165,12 +7298,12 @@ var cva = (base, config) => (props) => {
7165
7298
  var import_radix_ui2 = require("radix-ui");
7166
7299
  var import_jsx_runtime5 = require("react/jsx-runtime");
7167
7300
  var toggleVariants = cva(
7168
- "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",
7301
+ "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",
7169
7302
  {
7170
7303
  variants: {
7171
7304
  variant: {
7172
7305
  default: "bg-transparent border-0",
7173
- outline: "border border-input bg-transparent shadow-xs hover:bg-accent hover:text-accent-foreground"
7306
+ outline: "border border-input bg-transparent shadow-xs hover:bg-bridge-accent hover:text-accent-foreground"
7174
7307
  },
7175
7308
  size: {
7176
7309
  default: "px-2 py-1",
@@ -7263,10 +7396,10 @@ var DragHandle = React4.forwardRef(
7263
7396
  type,
7264
7397
  "data-slot": "drag-handle",
7265
7398
  className: cn(
7266
- "inline-flex h-7 w-4 shrink-0 items-center justify-center rounded-md transition-all duration-200 max-h-[30px]",
7399
+ "inline-flex h-7 w-4 shrink-0 items-center justify-center rounded-md transition-all duration-200 max-h-7.5",
7267
7400
  "bg-white border border-transparent text-stone-500 shadow-md cursor-grab",
7268
7401
  "enabled:hover:border enabled:hover:border-stone-200 enabled:hover:text-stone-950",
7269
- "enabled:active:border enabled:active:border-primary enabled:active:bg-primary-50 enabled:active:text-stone-950 enabled:active:shadow enabled:active:cursor-grabbing",
7402
+ "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",
7270
7403
  "disabled:cursor-not-allowed disabled:opacity-40 disabled:text-stone-950 disabled:pointer-events-none",
7271
7404
  className
7272
7405
  ),
@@ -7288,7 +7421,7 @@ var CustomToolbar = React5.forwardRef(({ className, onMouseDown, ...props }, ref
7288
7421
  "data-ohw-toolbar": "",
7289
7422
  className: cn(
7290
7423
  // Figma: bg background, radius 8, gap-1, p-0.5, shadow-md — no border
7291
- "inline-flex h-8 items-center gap-1 rounded-[var(--radius,0.5rem)] bg-background p-0.5 font-sans whitespace-nowrap shadow-md",
7424
+ "inline-flex h-8 items-center gap-1 rounded-(--radius,0.5rem) bg-background p-0.5 font-sans whitespace-nowrap shadow-md",
7292
7425
  className
7293
7426
  ),
7294
7427
  onMouseDown: (e) => {
@@ -7317,7 +7450,7 @@ var CustomToolbarButton = React5.forwardRef(
7317
7450
  type,
7318
7451
  className: cn(
7319
7452
  "inline-flex size-7 shrink-0 items-center justify-center rounded-[calc(var(--radius,0.5rem)-2px)] text-foreground transition-colors",
7320
- active ? "bg-primary text-primary-foreground" : "bg-transparent hover:bg-muted disabled:cursor-not-allowed disabled:text-muted-foreground disabled:opacity-60",
7453
+ active ? "bg-bridge-primary text-primary-foreground" : "bg-transparent hover:bg-muted disabled:cursor-not-allowed disabled:text-muted-foreground disabled:opacity-60",
7321
7454
  className
7322
7455
  ),
7323
7456
  ...props
@@ -8519,13 +8652,13 @@ function FormFieldToolbar({
8519
8652
  ]
8520
8653
  }
8521
8654
  ) }),
8522
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(DropdownMenuContent, { align: "start", sideOffset: 8, className: "min-w-[190px] p-1", children: FIELD_TYPES.map((entry) => {
8655
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(DropdownMenuContent, { align: "start", sideOffset: 8, className: "min-w-47.5 p-1", children: FIELD_TYPES.map((entry) => {
8523
8656
  const Icon = TYPE_ICONS[entry.type];
8524
8657
  return /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(
8525
8658
  DropdownMenuItem,
8526
8659
  {
8527
8660
  onSelect: () => onTypeChange(entry.type),
8528
- className: "rounded-md py-2 text-[13px] " + (entry.type === type ? "bg-primary/10" : ""),
8661
+ className: "rounded-md py-2 text-[13px] " + (entry.type === type ? "bg-bridge-primary/10" : ""),
8529
8662
  children: [
8530
8663
  /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(Icon, { size: 14, strokeWidth: 1.75, className: "shrink-0", "aria-hidden": true }),
8531
8664
  entry.label
@@ -8542,7 +8675,7 @@ function FormFieldToolbar({
8542
8675
  type: "button",
8543
8676
  "aria-pressed": required,
8544
8677
  onClick: onRequiredToggle,
8545
- 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"),
8678
+ 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"),
8546
8679
  "data-ohw-field-required-toggle": "",
8547
8680
  children: [
8548
8681
  /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_lucide_react4.Asterisk, { size: 14, strokeWidth: 2, "aria-hidden": true }),
@@ -8562,7 +8695,7 @@ function FormFieldToolbar({
8562
8695
  children: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_lucide_react4.MoreHorizontal, { size: 15, "aria-hidden": true })
8563
8696
  }
8564
8697
  ) }),
8565
- /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(DropdownMenuContent, { align: "start", sideOffset: 8, className: "min-w-[170px] p-1", children: [
8698
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(DropdownMenuContent, { align: "start", sideOffset: 8, className: "min-w-42.5 p-1", children: [
8566
8699
  /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(DropdownMenuItem, { onSelect: onDuplicate, className: "rounded-md py-2 text-[13px]", children: [
8567
8700
  /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_lucide_react4.Copy, { size: 14, strokeWidth: 1.75, className: "shrink-0", "aria-hidden": true }),
8568
8701
  "Duplicate"
@@ -8582,7 +8715,7 @@ function FieldTypePicker({ onPick }) {
8582
8715
  "div",
8583
8716
  {
8584
8717
  "data-ohw-field-type-picker": "",
8585
- className: "pointer-events-auto grid w-[280px] grid-cols-2 gap-2 rounded-xl border border-border bg-background p-3 shadow-lg",
8718
+ className: "pointer-events-auto grid w-105 grid-cols-3 gap-3 rounded-xl border border-border bg-background p-4 shadow-lg",
8586
8719
  children: FIELD_TYPES.map((entry) => {
8587
8720
  const Icon = TYPE_ICONS[entry.type];
8588
8721
  return /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(
@@ -8590,7 +8723,7 @@ function FieldTypePicker({ onPick }) {
8590
8723
  {
8591
8724
  type: "button",
8592
8725
  onClick: () => onPick(entry.type),
8593
- 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",
8726
+ 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",
8594
8727
  children: [
8595
8728
  /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(Icon, { size: 26, strokeWidth: 1.5, "aria-hidden": true }),
8596
8729
  entry.label
@@ -8616,7 +8749,7 @@ var buttonVariants = cva(
8616
8749
  {
8617
8750
  variants: {
8618
8751
  variant: {
8619
- default: "bg-primary text-primary-foreground hover:opacity-90",
8752
+ default: "bg-bridge-primary text-primary-foreground hover:opacity-90",
8620
8753
  outline: "border border-border bg-background text-foreground shadow-sm hover:bg-muted/80",
8621
8754
  ghost: "min-w-0 px-3 py-2 text-foreground hover:bg-muted/50"
8622
8755
  },
@@ -8817,8 +8950,8 @@ function MediaOverlay({
8817
8950
  pointerEvents: hover.hasTextOverlap ? "none" : "auto",
8818
8951
  // Selected: a firm component ring with no wash, so the image reads as chosen rather
8819
8952
  // than hovered. Hover keeps the existing tinted preview.
8820
- boxShadow: selected ? "inset 0 0 0 2px var(--color-primary)" : "inset 0 0 0 1.5px var(--color-primary)",
8821
- background: selected ? "transparent" : "color-mix(in srgb, var(--color-primary) 20%, transparent)"
8953
+ boxShadow: selected ? "inset 0 0 0 2px var(--color-bridge-primary)" : "inset 0 0 0 1.5px var(--color-bridge-primary)",
8954
+ background: selected ? "transparent" : "color-mix(in srgb, var(--color-bridge-primary) 20%, transparent)"
8822
8955
  },
8823
8956
  onClick: () => onSelect && !selected ? onSelect(hover.key) : onReplace(hover.key),
8824
8957
  children: [
@@ -8912,8 +9045,8 @@ function CarouselOverlay({
8912
9045
  height: rect.height,
8913
9046
  zIndex: 2147483646,
8914
9047
  pointerEvents: "auto",
8915
- boxShadow: "inset 0 0 0 1.5px var(--color-primary)",
8916
- background: "color-mix(in srgb, var(--color-primary) 20%, transparent)"
9048
+ boxShadow: "inset 0 0 0 1.5px var(--color-bridge-primary)",
9049
+ background: "color-mix(in srgb, var(--color-bridge-primary) 20%, transparent)"
8917
9050
  },
8918
9051
  onClick: () => onEdit(hover.key),
8919
9052
  children: /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(
@@ -9751,7 +9884,7 @@ function SectionTreeItem({
9751
9884
  /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
9752
9885
  "div",
9753
9886
  {
9754
- className: "mr-[-1px] h-9 w-2 shrink-0 rounded-bl-sm border-b border-l border-border mb-4",
9887
+ className: "-mr-px h-9 w-2 shrink-0 rounded-bl-sm border-b border-l border-border mb-4",
9755
9888
  "aria-hidden": true
9756
9889
  }
9757
9890
  ),
@@ -9770,7 +9903,7 @@ function SectionTreeItem({
9770
9903
  className: cn(
9771
9904
  "flex h-9 min-w-0 flex-1 items-center gap-2 rounded-md border border-border bg-background p-3",
9772
9905
  interactive && "cursor-pointer hover:bg-muted/30",
9773
- interactive && selected && "border-primary"
9906
+ interactive && selected && "border-bridge-primary"
9774
9907
  ),
9775
9908
  children: [
9776
9909
  /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
@@ -9900,7 +10033,7 @@ function UrlOrPageInput({
9900
10033
  };
9901
10034
  const fieldClassName = cn(
9902
10035
  "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]",
9903
- urlError ? "border-destructive shadow-[0_0_0_1px_var(--ohw-destructive)]" : isFocused ? "border-primary shadow-[0_0_0_1px_var(--ohw-primary)]" : "border-input"
10036
+ 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"
9904
10037
  );
9905
10038
  return /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { className: "flex w-full flex-col gap-2 p-0", children: [
9906
10039
  /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(Label, { htmlFor: inputId, className: cn(urlError && "text-destructive"), children: "Destination" }),
@@ -13978,7 +14111,7 @@ function DisplaySwitch({
13978
14111
  onClick: () => onChange(!checked),
13979
14112
  className: cn(
13980
14113
  "relative h-5 w-9 shrink-0 rounded-full transition-colors",
13981
- checked ? "bg-primary" : "bg-primary-50",
14114
+ checked ? "bg-bridge-primary" : "bg-primary-50",
13982
14115
  disabled ? "cursor-default opacity-50" : "cursor-pointer"
13983
14116
  ),
13984
14117
  children: /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
@@ -13986,7 +14119,7 @@ function DisplaySwitch({
13986
14119
  {
13987
14120
  className: cn(
13988
14121
  "absolute top-0.5 h-4 w-4 rounded-full bg-white transition-all",
13989
- checked ? "left-[1.125rem]" : "left-0.5"
14122
+ checked ? "left-4.5" : "left-0.5"
13990
14123
  )
13991
14124
  }
13992
14125
  )
@@ -15602,7 +15735,7 @@ var badgeVariants = cva(
15602
15735
  {
15603
15736
  variants: {
15604
15737
  variant: {
15605
- default: "border-transparent bg-primary text-primary-foreground",
15738
+ default: "border-transparent bg-bridge-primary text-primary-foreground",
15606
15739
  secondary: "border-transparent bg-secondary text-secondary-foreground hover:bg-secondary/80",
15607
15740
  destructive: "border-transparent bg-destructive text-destructive-foreground hover:bg-destructive/80",
15608
15741
  outline: "text-foreground"
@@ -18991,7 +19124,9 @@ function OhhwellsBridge() {
18991
19124
  }, [isEditMode]);
18992
19125
  (0, import_react17.useEffect)(() => {
18993
19126
  if (isEditMode || fetchState !== "done") return;
19127
+ console.log("env", process.env.NEXT_PUBLIC_FLOWOPS_API_URL);
18994
19128
  const apiUrl = process.env.NEXT_PUBLIC_FLOWOPS_API_URL ?? "https://flowops-backend-staging-2yfdh7pwpq-as.a.run.app";
19129
+ console.log({ apiUrl, subdomain });
18995
19130
  bindPublishedForms(apiUrl, subdomain, contentCache.get(subdomain) ?? {});
18996
19131
  }, [isEditMode, fetchState, subdomain]);
18997
19132
  (0, import_react17.useEffect)(() => {
@@ -21198,10 +21333,26 @@ function OhhwellsBridge() {
21198
21333
  const handleGetBrand = (e) => {
21199
21334
  if (e.data?.type !== "ow:get-brand") return;
21200
21335
  const template = deriveTemplateBrand();
21201
- const value = brandKitRef.current || (template ? JSON.stringify(template) : "");
21336
+ const fallback = template ?? (() => {
21337
+ const fonts = deriveTemplateFonts();
21338
+ return fonts ? { palette: AI_DEFAULT_BRAND.palette, fonts } : null;
21339
+ })();
21340
+ const value = brandKitRef.current || (fallback ? JSON.stringify(fallback) : "");
21202
21341
  postToParentRef.current({ type: "ow:brand-value", value });
21203
21342
  };
21204
21343
  window.addEventListener("message", handleGetBrand);
21344
+ const handleGetTemplateFonts = (e) => {
21345
+ if (e.data?.type !== "ow:get-template-fonts") return;
21346
+ const fonts = deriveTemplateFonts();
21347
+ postToParentRef.current({ type: "ow:template-fonts-value", value: fonts ? JSON.stringify(fonts) : "" });
21348
+ };
21349
+ window.addEventListener("message", handleGetTemplateFonts);
21350
+ const handleGetTemplateBrand = (e) => {
21351
+ if (e.data?.type !== "ow:get-template-brand") return;
21352
+ const brand = deriveTemplateBrand();
21353
+ postToParentRef.current({ type: "ow:template-brand-value", value: brand ? JSON.stringify(brand) : "" });
21354
+ };
21355
+ window.addEventListener("message", handleGetTemplateBrand);
21205
21356
  const handleMoveSection = (e) => {
21206
21357
  if (e.data?.type !== "ow:move-section") return;
21207
21358
  const instanceId = typeof e.data.instanceId === "string" ? e.data.instanceId : "";
@@ -22042,6 +22193,8 @@ function OhhwellsBridge() {
22042
22193
  window.removeEventListener("message", handleAiSetBrand);
22043
22194
  window.removeEventListener("message", handleAiSetStyles);
22044
22195
  window.removeEventListener("message", handleGetBrand);
22196
+ window.removeEventListener("message", handleGetTemplateFonts);
22197
+ window.removeEventListener("message", handleGetTemplateBrand);
22045
22198
  window.removeEventListener("message", handleMoveSection);
22046
22199
  window.removeEventListener("message", handlePanelDragging);
22047
22200
  window.removeEventListener("message", handleDeleteSection);
@@ -22253,7 +22406,7 @@ function OhhwellsBridge() {
22253
22406
  postToParent2({
22254
22407
  type: "ow:ready",
22255
22408
  version: "1",
22256
- bridgeVersion: "0.1.92",
22409
+ bridgeVersion: "0.1.93",
22257
22410
  path: pathname,
22258
22411
  nodes: collectEditableNodes(editContentRef.current),
22259
22412
  sections
@@ -22869,7 +23022,7 @@ function OhhwellsBridge() {
22869
23022
  "span",
22870
23023
  {
22871
23024
  "data-ohw-form-count": "",
22872
- 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",
23025
+ 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",
22873
23026
  children: formPickCount
22874
23027
  }
22875
23028
  )
@@ -23106,11 +23259,11 @@ function OhhwellsBridge() {
23106
23259
  className: "fixed left-0 w-full z-2147483646 flex items-center pointer-events-none",
23107
23260
  style: { top: sectionGap.y, transform: "translateY(-50%)" },
23108
23261
  children: [
23109
- /* @__PURE__ */ (0, import_jsx_runtime33.jsx)("div", { className: "flex-1 bg-primary", style: { height: 3 } }),
23262
+ /* @__PURE__ */ (0, import_jsx_runtime33.jsx)("div", { className: "flex-1 bg-bridge-primary", style: { height: 3 } }),
23110
23263
  /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
23111
23264
  Badge,
23112
23265
  {
23113
- 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",
23266
+ 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",
23114
23267
  onClick: () => {
23115
23268
  window.parent.postMessage(
23116
23269
  {
@@ -23124,7 +23277,7 @@ function OhhwellsBridge() {
23124
23277
  children: "Add Section"
23125
23278
  }
23126
23279
  ),
23127
- /* @__PURE__ */ (0, import_jsx_runtime33.jsx)("div", { className: "flex-1 bg-primary", style: { height: 3 } })
23280
+ /* @__PURE__ */ (0, import_jsx_runtime33.jsx)("div", { className: "flex-1 bg-bridge-primary", style: { height: 3 } })
23128
23281
  ]
23129
23282
  }
23130
23283
  ),