@timbal-ai/timbal-react 0.8.1 → 0.8.2

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/CHANGELOG.md CHANGED
@@ -2,6 +2,25 @@
2
2
 
3
3
  All notable changes to `@timbal-ai/timbal-react` are documented here.
4
4
 
5
+ ## [0.8.2] — 2026-06-02
6
+
7
+ ### Added
8
+
9
+ - **Full theme personalities** — extend programmatic theming beyond brand color to **roundness, shadows, and fonts** in one intent object:
10
+ - **`createTimbalTheme`** — new options: `shadow` (`none` | `hairline` | `soft` | `medium` | `strong`), `typography` (`sans`, optional `display`/`mono`, `importUrl` for web fonts). `radius` now also sets `--radius-2xl` (composer shell). Returns `fontFamily` + `fontImportUrl` for runtime font loading.
11
+ - **`themeToCss(theme, { scope?, includeFontImport? })`** — emits a `font-family: var(--font-sans)` rule when the theme carries a font; optional `@import` for standalone stylesheets.
12
+ - **`ensureThemeFontLink(url)`** — inject/remove a managed font `<link>` in `<head>`.
13
+ - **`applyTimbalTheme` / `TimbalThemeStyle`** — auto-load preset/custom web fonts via `<link>`.
14
+ - **`TIMBAL_THEME_PRESETS`** — each preset is now a full personality (color + radius + shadow + font), not color-only. New presets: **`folio`** (Fraunces serif, sharp corners), **`carbon`** (JetBrains Mono, green accent). Existing presets (`indigo`, `violet`, …) ship distinct fonts and radii.
15
+ - **`ThemePresetGallery`** — shows font name on each swatch card.
16
+ - **`THEME_AGENT_INSTRUCTIONS`** — documents typography, shadow, and font-loading rules for UI-generation agents.
17
+
18
+ ### Changed
19
+
20
+ - **`TimbalThemePreset`** — adds optional `font` label for pickers.
21
+
22
+ ---
23
+
5
24
  ## [0.8.1] — 2026-06-02
6
25
 
7
26
  ### Added
package/README.md CHANGED
@@ -73,20 +73,30 @@ Both light AND dark blocks must be defined for every overridden token — otherw
73
73
 
74
74
  ### Programmatic theming (no hand-authored OKLCH)
75
75
 
76
- Instead of hand-writing paired `:root` / `.dark` blocks, derive a complete, contrast-correct palette from a single brand color. The package owns the OKLCH math for every token (primary, foreground, ring, the full button gradient, the playground tint):
76
+ Instead of hand-writing paired `:root` / `.dark` blocks, derive a complete **personality** — color, roundness, shadows, and fonts — from a single intent object. The package owns the OKLCH math for every color token (primary, foreground, ring, the full button gradient, the playground tint):
77
77
 
78
78
  ```ts
79
79
  import { createTimbalTheme, themeToCss, applyTimbalTheme } from "@timbal-ai/timbal-react";
80
80
 
81
- const theme = createTimbalTheme({ brand: "#4f46e5", radius: 0.75 });
81
+ const theme = createTimbalTheme({
82
+ brand: "#4f46e5",
83
+ radius: 0.875, // corner roundness (rem) → --radius + --radius-2xl
84
+ shadow: "soft", // "none" | "hairline" | "soft" | "medium" | "strong"
85
+ typography: { // optional — re-skins every component's font
86
+ sans: '"Geist", ui-sans-serif, system-ui, sans-serif',
87
+ importUrl: "https://fonts.googleapis.com/css2?family=Geist:wght@400..600&display=swap",
88
+ },
89
+ });
82
90
 
83
91
  // Build-time / SSR — paste into index.css (paired light + dark, always in sync):
84
92
  const css = themeToCss(theme);
85
93
 
86
- // Runtime — inject a managed <style>, swappable, returns a disposer:
94
+ // Runtime — inject a managed <style> (+ font <link>), swappable, returns a disposer:
87
95
  const dispose = applyTimbalTheme(theme);
88
96
  ```
89
97
 
98
+ > **Fonts must be loaded.** `applyTimbalTheme` and `TimbalThemeStyle` inject the `<link>` for `typography.importUrl` automatically. For build-time `themeToCss`, add the `<link rel="stylesheet">` to `index.html` yourself (or pass `themeToCss(theme, { includeFontImport: true })` when the result is a standalone stylesheet).
99
+
90
100
  Or render it as a component near your app root:
91
101
 
92
102
  ```tsx
@@ -98,7 +108,7 @@ import { TimbalThemeStyle } from "@timbal-ai/timbal-react";
98
108
 
99
109
  ### Presets + the picker
100
110
 
101
- A small closed catalog (`TIMBAL_THEME_PRESETS`: `platform`, `indigo`, `violet`, `forest`, `warm`, `slate`) lets you offer styles by stable id and apply on selection. `ThemePresetGallery` previews each option with real components, scoped so the live app doesn't change until the user picks:
111
+ A small closed catalog (`TIMBAL_THEME_PRESETS`) lets you offer styles by stable id and apply on selection. Each preset is a **full personality** (color + radius + shadows + font), not just a color: `platform` (system), `indigo` (Geist), `violet` (Sora), `forest`/`warm` (Lexend), `slate` (Inter), `folio` (Fraunces serif), `carbon` (JetBrains Mono). `ThemePresetGallery` previews each option with real components, scoped so the live app doesn't change until the user picks:
102
112
 
103
113
  ```tsx
104
114
  import { ThemePresetGallery, applyThemePreset } from "@timbal-ai/timbal-react";
package/dist/app.cjs CHANGED
@@ -98,6 +98,7 @@ __export(app_exports, {
98
98
  clearTimbalTheme: () => clearTimbalTheme,
99
99
  connectionRowListClass: () => connectionRowListClass,
100
100
  createTimbalTheme: () => createTimbalTheme,
101
+ ensureThemeFontLink: () => ensureThemeFontLink,
101
102
  getStoredThemePreset: () => getStoredThemePreset,
102
103
  getThemePreset: () => getThemePreset,
103
104
  themeToCss: () => themeToCss,
@@ -431,6 +432,38 @@ function relativeLuminance(color) {
431
432
  }
432
433
 
433
434
  // src/design/theme.ts
435
+ var SHADOW_PRESETS = {
436
+ none: {
437
+ lightCard: "none",
438
+ lightElevated: "none",
439
+ darkCard: "none",
440
+ darkElevated: "none"
441
+ },
442
+ hairline: {
443
+ lightCard: "0 0 0 1px rgba(15, 23, 42, 0.06)",
444
+ lightElevated: "0 1px 2px rgba(15, 23, 42, 0.06)",
445
+ darkCard: "0 0 0 1px rgba(255, 255, 255, 0.06)",
446
+ darkElevated: "0 2px 8px rgba(0, 0, 0, 0.4)"
447
+ },
448
+ soft: {
449
+ lightCard: "0 1px 2px rgba(15, 23, 42, 0.04)",
450
+ lightElevated: "0 8px 30px rgba(15, 23, 42, 0.07)",
451
+ darkCard: "0 1px 2px rgba(0, 0, 0, 0.3)",
452
+ darkElevated: "0 10px 34px rgba(0, 0, 0, 0.45)"
453
+ },
454
+ medium: {
455
+ lightCard: "0 1px 2px -0.5px rgba(0, 0, 0, 0.05)",
456
+ lightElevated: "0 4px 24px rgba(0, 0, 0, 0.06)",
457
+ darkCard: "0 1px 3px rgba(0, 0, 0, 0.22)",
458
+ darkElevated: "0 4px 24px rgba(0, 0, 0, 0.35)"
459
+ },
460
+ strong: {
461
+ lightCard: "0 2px 6px rgba(15, 23, 42, 0.10)",
462
+ lightElevated: "0 16px 48px rgba(15, 23, 42, 0.16)",
463
+ darkCard: "0 2px 6px rgba(0, 0, 0, 0.4)",
464
+ darkElevated: "0 18px 50px rgba(0, 0, 0, 0.6)"
465
+ }
466
+ };
434
467
  function primaryForMode(brand, mode) {
435
468
  if (mode === "light") {
436
469
  return { ...brand, l: Math.min(Math.max(brand.l, 0.42), 0.68) };
@@ -466,8 +499,26 @@ function createTimbalTheme(intent) {
466
499
  const light = {};
467
500
  const dark = {};
468
501
  const root = {};
502
+ let fontFamily;
503
+ let fontImportUrl;
469
504
  if (typeof intent.radius === "number") {
470
505
  root["--radius"] = `${intent.radius}rem`;
506
+ root["--radius-2xl"] = `${Math.max(intent.radius + 0.25, 0)}rem`;
507
+ }
508
+ if (intent.typography) {
509
+ const { sans, display, mono, importUrl } = intent.typography;
510
+ root["--font-sans"] = sans;
511
+ if (display) root["--font-display"] = display;
512
+ if (mono) root["--font-mono"] = mono;
513
+ fontFamily = sans;
514
+ fontImportUrl = importUrl;
515
+ }
516
+ if (intent.shadow) {
517
+ const s = SHADOW_PRESETS[intent.shadow];
518
+ light["--shadow-card-value"] = s.lightCard;
519
+ light["--shadow-card-elevated-value"] = s.lightElevated;
520
+ dark["--shadow-card-value"] = s.darkCard;
521
+ dark["--shadow-card-elevated-value"] = s.darkElevated;
471
522
  }
472
523
  const primaryLight = primaryForMode(brand, "light");
473
524
  const primaryDark = primaryForMode(brand, "dark");
@@ -565,7 +616,7 @@ function createTimbalTheme(intent) {
565
616
  );
566
617
  }
567
618
  }
568
- return { light, dark, root };
619
+ return { light, dark, root, fontFamily, fontImportUrl };
569
620
  }
570
621
  function declarations(map, indent) {
571
622
  return Object.entries(map).map(([name, value]) => `${indent}${name}: ${value};`).join("\n");
@@ -588,6 +639,11 @@ ${declarations(theme.dark, indent)}
588
639
  }`
589
640
  );
590
641
  }
642
+ if (theme.fontFamily) {
643
+ blocks.push(`${sel} {
644
+ ${indent}font-family: var(--font-sans);
645
+ }`);
646
+ }
591
647
  } else {
592
648
  if (Object.keys(lightVars).length) {
593
649
  blocks.push(`:root {
@@ -597,15 +653,45 @@ ${declarations(lightVars, indent)}
597
653
  if (Object.keys(theme.dark).length) {
598
654
  blocks.push(`.dark {
599
655
  ${declarations(theme.dark, indent)}
656
+ }`);
657
+ }
658
+ if (theme.fontFamily) {
659
+ blocks.push(`:root,
660
+ body {
661
+ ${indent}font-family: var(--font-sans);
600
662
  }`);
601
663
  }
602
664
  }
603
- return blocks.join("\n\n");
665
+ const css = blocks.join("\n\n");
666
+ if (options.includeFontImport && theme.fontImportUrl) {
667
+ return `@import url("${theme.fontImportUrl}");
668
+
669
+ ${css}`;
670
+ }
671
+ return css;
604
672
  }
605
673
  var RUNTIME_STYLE_ID = "timbal-theme-runtime";
674
+ var FONT_LINK_ATTR = "data-timbal-theme-font";
675
+ function ensureThemeFontLink(url) {
676
+ if (typeof document === "undefined") return;
677
+ const existing = document.head.querySelector(
678
+ `link[${FONT_LINK_ATTR}]`
679
+ );
680
+ if (!url) {
681
+ existing?.remove();
682
+ return;
683
+ }
684
+ if (existing?.getAttribute("href") === url) return;
685
+ const link = existing ?? document.createElement("link");
686
+ link.rel = "stylesheet";
687
+ link.href = url;
688
+ link.setAttribute(FONT_LINK_ATTR, "");
689
+ if (!existing) document.head.appendChild(link);
690
+ }
606
691
  function applyTimbalTheme(theme) {
607
692
  if (typeof document === "undefined") return () => {
608
693
  };
694
+ ensureThemeFontLink(theme.fontImportUrl);
609
695
  let el = document.getElementById(RUNTIME_STYLE_ID);
610
696
  if (!el) {
611
697
  el = document.createElement("style");
@@ -616,11 +702,13 @@ function applyTimbalTheme(theme) {
616
702
  el.textContent = themeToCss(theme);
617
703
  return () => {
618
704
  el?.parentNode?.removeChild(el);
705
+ ensureThemeFontLink(void 0);
619
706
  };
620
707
  }
621
708
  function clearTimbalTheme() {
622
709
  if (typeof document === "undefined") return;
623
710
  document.getElementById(RUNTIME_STYLE_ID)?.remove();
711
+ ensureThemeFontLink(void 0);
624
712
  }
625
713
  function isDev() {
626
714
  if (typeof process !== "undefined" && process.env?.NODE_ENV === "production") {
@@ -671,48 +759,122 @@ var STORAGE_KEYS = {
671
759
 
672
760
  // src/design/theme-presets.ts
673
761
  var EMPTY_TOKENS = { light: {}, dark: {}, root: {} };
762
+ var FONT_URL = {
763
+ geist: "https://fonts.googleapis.com/css2?family=Geist:wght@400..600&display=swap",
764
+ sora: "https://fonts.googleapis.com/css2?family=Sora:wght@400..600&display=swap",
765
+ lexend: "https://fonts.googleapis.com/css2?family=Lexend:wght@400..600&display=swap",
766
+ inter: "https://fonts.googleapis.com/css2?family=Inter:wght@400..600&display=swap",
767
+ fraunces: "https://fonts.googleapis.com/css2?family=Fraunces:opsz,wght@9..144,400..600&display=swap",
768
+ jetbrains: "https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@400..600&display=swap"
769
+ };
770
+ var STACK = {
771
+ geist: '"Geist", ui-sans-serif, system-ui, sans-serif',
772
+ sora: '"Sora", ui-sans-serif, system-ui, sans-serif',
773
+ lexend: '"Lexend", ui-sans-serif, system-ui, sans-serif',
774
+ inter: '"Inter", ui-sans-serif, system-ui, sans-serif',
775
+ fraunces: '"Fraunces", ui-serif, Georgia, "Times New Roman", serif',
776
+ jetbrains: '"JetBrains Mono", ui-monospace, SFMono-Regular, Menlo, monospace'
777
+ };
674
778
  var TIMBAL_THEME_PRESETS = [
675
779
  {
676
780
  id: "platform",
677
781
  label: "Platform",
678
- description: "Shipped neutral monochrome \u2014 the Timbal Platform default. Calm, brand-agnostic.",
782
+ description: "Shipped neutral monochrome \u2014 the Timbal Platform default. Calm, brand-agnostic, system font.",
679
783
  swatch: "oklch(0.205 0 0)",
784
+ font: null,
680
785
  tokens: EMPTY_TOKENS
681
786
  },
682
787
  {
683
788
  id: "indigo",
684
789
  label: "Indigo",
685
- description: "Cool, trustworthy blue-violet \u2014 good for analytics & ops dashboards.",
790
+ description: "Cool, trustworthy blue-violet, Geist type, generous radius, soft shadows \u2014 analytics & ops dashboards.",
686
791
  swatch: "#4f46e5",
687
- tokens: createTimbalTheme({ brand: "#4f46e5" })
792
+ font: "Geist",
793
+ tokens: createTimbalTheme({
794
+ brand: "#4f46e5",
795
+ radius: 0.875,
796
+ shadow: "soft",
797
+ typography: { sans: STACK.geist, importUrl: FONT_URL.geist }
798
+ })
688
799
  },
689
800
  {
690
801
  id: "violet",
691
802
  label: "Violet",
692
- description: "Vivid purple \u2014 expressive, product/marketing-leaning surfaces.",
803
+ description: "Vivid purple, Sora type, rounded, soft shadows \u2014 expressive product / marketing surfaces.",
693
804
  swatch: "#7c3aed",
694
- tokens: createTimbalTheme({ brand: "#7c3aed" })
805
+ font: "Sora",
806
+ tokens: createTimbalTheme({
807
+ brand: "#7c3aed",
808
+ radius: 1,
809
+ shadow: "soft",
810
+ typography: { sans: STACK.sora, importUrl: FONT_URL.sora }
811
+ })
695
812
  },
696
813
  {
697
814
  id: "forest",
698
815
  label: "Forest",
699
- description: "Grounded green \u2014 finance, sustainability, status-positive apps.",
816
+ description: "Grounded green, Lexend type, compact radius \u2014 finance, sustainability, status-positive apps.",
700
817
  swatch: "#16a34a",
701
- tokens: createTimbalTheme({ brand: "#16a34a" })
818
+ font: "Lexend",
819
+ tokens: createTimbalTheme({
820
+ brand: "#16a34a",
821
+ radius: 0.625,
822
+ shadow: "soft",
823
+ typography: { sans: STACK.lexend, importUrl: FONT_URL.lexend }
824
+ })
702
825
  },
703
826
  {
704
827
  id: "warm",
705
828
  label: "Warm",
706
- description: "Energetic orange \u2014 consumer, creative, high-engagement tools.",
829
+ description: "Energetic orange, Lexend type, friendly radius \u2014 consumer, creative, high-engagement tools.",
707
830
  swatch: "#ea580c",
708
- tokens: createTimbalTheme({ brand: "#ea580c" })
831
+ font: "Lexend",
832
+ tokens: createTimbalTheme({
833
+ brand: "#ea580c",
834
+ radius: 0.875,
835
+ shadow: "soft",
836
+ typography: { sans: STACK.lexend, importUrl: FONT_URL.lexend }
837
+ })
709
838
  },
710
839
  {
711
840
  id: "slate",
712
841
  label: "Slate",
713
- description: "Muted cool gray-blue with a subtle tint \u2014 understated enterprise.",
842
+ description: "Muted enterprise gray-blue, Inter type, tight radius, hairline shadows, tinted neutrals.",
714
843
  swatch: "#475569",
715
- tokens: createTimbalTheme({ brand: "#475569", tintNeutrals: true })
844
+ font: "Inter",
845
+ tokens: createTimbalTheme({
846
+ brand: "#475569",
847
+ radius: 0.5,
848
+ shadow: "hairline",
849
+ tintNeutrals: true,
850
+ typography: { sans: STACK.inter, importUrl: FONT_URL.inter }
851
+ })
852
+ },
853
+ {
854
+ id: "folio",
855
+ label: "Folio",
856
+ description: "Editorial serif (Fraunces), near-sharp corners, hairline shadows \u2014 content / docs / reports.",
857
+ swatch: "#9a3412",
858
+ font: "Fraunces",
859
+ tokens: createTimbalTheme({
860
+ brand: "#9a3412",
861
+ radius: 0.25,
862
+ shadow: "hairline",
863
+ typography: { sans: STACK.fraunces, importUrl: FONT_URL.fraunces }
864
+ })
865
+ },
866
+ {
867
+ id: "carbon",
868
+ label: "Carbon",
869
+ description: "Terminal monospace (JetBrains Mono), crisp corners, green accent \u2014 developer / infra tools.",
870
+ swatch: "#15803d",
871
+ font: "JetBrains Mono",
872
+ tokens: createTimbalTheme({
873
+ brand: "#15803d",
874
+ radius: 0.375,
875
+ shadow: "hairline",
876
+ typography: { sans: STACK.jetbrains, importUrl: FONT_URL.jetbrains }
877
+ })
716
878
  }
717
879
  ];
718
880
  var PRESET_BY_ID = new Map(
@@ -753,18 +915,29 @@ The package ships a complete light + dark token system (\`styles.css\`). Compone
753
915
 
754
916
  **Never write \`oklch(...)\` / hex literals or hand-author paired \`:root\` + \`.dark\` blocks.** Express intent and let the package derive a complete, contrast-correct, paired palette.
755
917
 
756
- ### Pick a brand color (rebrand)
918
+ ### Generate a full personality (color + roundness + fonts + shadows)
757
919
 
758
920
  \`\`\`ts
759
921
  import { createTimbalTheme, themeToCss } from "@timbal-ai/timbal-react";
760
922
 
761
- const theme = createTimbalTheme({ brand: "#4f46e5" /* accent?, radius?, tintNeutrals? */ });
762
- // Build-time: write once into your app CSS (paired light + dark, guaranteed in sync):
763
- const css = themeToCss(theme);
923
+ const theme = createTimbalTheme({
924
+ brand: "#4f46e5",
925
+ radius: 0.875, // corner roundness in rem (sets --radius + --radius-2xl)
926
+ shadow: "soft", // "none" | "hairline" | "soft" | "medium" | "strong"
927
+ tintNeutrals: false, // tint background/border toward the brand hue
928
+ accent: "#10b981", // optional secondary accent
929
+ typography: { // optional \u2014 re-skins every component's font
930
+ sans: '"Geist", ui-sans-serif, system-ui, sans-serif',
931
+ importUrl: "https://fonts.googleapis.com/css2?family=Geist:wght@400..600&display=swap",
932
+ // display?, mono? also supported
933
+ },
934
+ });
935
+ const css = themeToCss(theme); // paired light + dark, guaranteed in sync
764
936
  \`\`\`
765
937
 
766
- - For a real company, look up the actual brand hex first (brandfetch / "<company> brand color hex"), then pass it as \`brand\`.
767
- - \`createTimbalTheme\` derives \`--primary\`, its foreground, ring, the full button gradient, and a soft playground tint. You only supply intent.
938
+ - \`createTimbalTheme\` derives \`--primary\`, its foreground, ring, the full button gradient, and a soft playground tint from \`brand\`. \`radius\` sets roundness, \`shadow\` sets card depth, \`typography\` sets fonts. You only supply intent \u2014 never raw OKLCH.
939
+ - For a real company, look up the actual brand hex first (brandfetch / "<company> brand color hex").
940
+ - **Web fonts must be loaded.** \`applyTimbalTheme\` / \`TimbalThemeStyle\` inject the \`<link>\` for \`typography.importUrl\` automatically. For build-time \`themeToCss\`, add the \`<link rel="stylesheet" href="\u2026">\` to your \`index.html\` yourself (or pass \`themeToCss(theme, { includeFontImport: true })\` when the result is a standalone stylesheet).
768
941
 
769
942
  ### Apply a theme
770
943
 
@@ -781,14 +954,18 @@ import { TIMBAL_THEME_PRESETS, applyThemePreset } from "@timbal-ai/timbal-react"
781
954
  // TIMBAL_THEME_PRESETS: { id, label, description, swatch, tokens }[]
782
955
  \`\`\`
783
956
 
784
- | Preset id | Use when |
785
- |-----------|----------|
786
- | \`platform\` | Neutral monochrome default (no brand) |
787
- | \`indigo\` | Cool, trustworthy \u2014 analytics / ops dashboards |
788
- | \`violet\` | Expressive purple \u2014 product / marketing |
789
- | \`forest\` | Green \u2014 finance, sustainability, positive status |
790
- | \`warm\` | Orange \u2014 consumer / creative / high-engagement |
791
- | \`slate\` | Muted enterprise gray-blue (tinted neutrals) |
957
+ Each preset is a **full personality** (color + radius + shadows + font), not just a color:
958
+
959
+ | Preset id | Personality |
960
+ |-----------|-------------|
961
+ | \`platform\` | Neutral monochrome, system font (the default \u2014 no brand) |
962
+ | \`indigo\` | Blue-violet, Geist, generous radius, soft shadows \u2014 analytics / ops |
963
+ | \`violet\` | Purple, Sora, rounded \u2014 product / marketing |
964
+ | \`forest\` | Green, Lexend, compact \u2014 finance / sustainability |
965
+ | \`warm\` | Orange, Lexend, friendly \u2014 consumer / creative |
966
+ | \`slate\` | Enterprise gray-blue, Inter, tight radius, hairline shadows |
967
+ | \`folio\` | Editorial serif (Fraunces), near-sharp corners \u2014 content / docs |
968
+ | \`carbon\` | Terminal monospace (JetBrains Mono), green accent \u2014 dev / infra |
792
969
 
793
970
  - To present options visually, render \`<ThemePresetGallery value={id} onSelect={setId} />\` \u2014 each swatch previews real components (Button + metric tile) scoped via \`data-timbal-theme\`, so the live app doesn't change until the user picks.
794
971
  - On selection, call \`applyThemePreset(id)\` (persists to \`localStorage\` and restores on reload).
@@ -812,14 +989,17 @@ var TimbalThemeStyle = ({
812
989
  if (!tokens) return null;
813
990
  const css = themeToCss(tokens, scope ? { scope } : void 0);
814
991
  if (!css) return null;
815
- return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
816
- "style",
817
- {
818
- "data-timbal-theme-style": scope ?? "root",
819
- nonce,
820
- dangerouslySetInnerHTML: { __html: css }
821
- }
822
- );
992
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
993
+ tokens.fontImportUrl ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("link", { rel: "stylesheet", href: tokens.fontImportUrl }) : null,
994
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
995
+ "style",
996
+ {
997
+ "data-timbal-theme-style": scope ?? "root",
998
+ nonce,
999
+ dangerouslySetInnerHTML: { __html: css }
1000
+ }
1001
+ )
1002
+ ] });
823
1003
  };
824
1004
 
825
1005
  // src/utils.ts
@@ -1403,6 +1583,10 @@ var ThemePresetGallery = ({
1403
1583
  selected ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "text-xs font-medium text-primary", children: "Selected" }) : null
1404
1584
  ] }),
1405
1585
  /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("p", { className: "text-xs leading-snug text-muted-foreground", children: preset.description }),
1586
+ preset.font ? /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("span", { className: "text-[10px] uppercase tracking-wide text-muted-foreground", children: [
1587
+ "Aa \xB7 ",
1588
+ preset.font
1589
+ ] }) : null,
1406
1590
  /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "flex flex-col gap-2 rounded-lg border border-border bg-background p-2", children: [
1407
1591
  /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "flex items-center gap-2", children: [
1408
1592
  /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(Button, { size: "xs", className: "pointer-events-none", children: "Primary" }),
@@ -7446,6 +7630,7 @@ function TimbalChat({
7446
7630
  clearTimbalTheme,
7447
7631
  connectionRowListClass,
7448
7632
  createTimbalTheme,
7633
+ ensureThemeFontLink,
7449
7634
  getStoredThemePreset,
7450
7635
  getThemePreset,
7451
7636
  themeToCss,
package/dist/app.d.cts CHANGED
@@ -1,4 +1,4 @@
1
- export { A as APP_KIT_AGENT_INSTRUCTIONS, a as AppChatPanel, b as AppChatPanelProps, c as AppConfirmDialog, d as AppConfirmDialogProps, e as AppCopilotContextValue, f as AppCopilotProvider, g as AppCopilotProviderProps, h as AppShell, i as AppShellChatControls, j as AppShellChatTrigger, k as AppShellChatTriggerProps, l as AppShellProps, m as AppShellTopbar, n as AppShellTopbarProps, B as BreadcrumbItem, o as Breadcrumbs, p as BreadcrumbsProps, C as CHART_PALETTE, q as ChartArtifactView, r as ChartLayout, s as ChartPanel, t as ChartPanelProps, u as ChartSeries, v as ChartVariant, w as ConnectionRow, x as ConnectionRowList, y as ConnectionRowListProps, z as ConnectionRowProps, D as DangerZone, E as DangerZoneAction, F as DangerZoneActionProps, G as DangerZoneProps, H as DataTable, I as DataTableColumn, J as DataTableProps, K as DataTableSort, L as DataTableSortDirection, M as DescriptionItem, N as DescriptionList, O as DescriptionListProps, P as EmptyState, Q as EmptyStateProps, R as ExpandableSection, S as ExpandableSectionProps, T as Field, U as FieldInput, V as FieldInputProps, W as FieldProps, X as FieldRow, Y as FieldRowProps, Z as FieldSelect, _ as FieldSelectProps, $ as FieldSwitch, a0 as FieldSwitchProps, a1 as FieldTextarea, a2 as FieldTextareaProps, a3 as FilterBar, a4 as FilterBarProps, a5 as FloatingUnsavedChangesBar, a6 as FloatingUnsavedChangesBarProps, a7 as FormSection, a8 as FormSectionProps, a9 as INTEGRATION_CATALOG_CARD_HEIGHT_CLASS, aa as InfoCard, ab as InfoCardProps, ac as InfoCardTone, ad as IntegrationCard, ae as IntegrationCardProps, af as IntegrationCardStatus, ag as IntegrationsEmptyState, ah as IntegrationsEmptyStateProps, ai as LineAreaChart, aj as LineAreaChartProps, ak as MetricChartCard, al as MetricChartCardProps, am as MetricChartMetric, an as MetricRow, ao as MetricRowItem, ap as MetricRowProps, aq as MetricTile, ar as MetricTileProps, as as Page, at as PageHeader, au as PageHeaderProps, av as PageProps, aw as PlanBadge, ax as PlanBadgeProps, ay as PlanBadgeTone, az as ResourceCard, aA as ResourceCardProps, aB as SearchInput, aC as SearchInputProps, aD as Section, aE as SectionProps, aF as SettingsSection, aG as SettingsSectionHeader, aH as SettingsSectionHeaderProps, aI as SettingsSectionProps, aJ as Sparkline, aK as SparklineProps, aL as StatTile, aM as StatTileProps, aN as StatusBadge, aO as StatusBadgeProps, aP as StatusBadgeTone, aQ as StatusDot, aR as StatusDotProps, aS as StatusDotTone, aT as SubNav, aU as SubNavItem, aV as SubNavProps, aW as SurfaceCard, aX as SurfaceCardProps, aY as THEME_AGENT_INSTRUCTIONS, aZ as TIMBAL_THEME_PRESETS, a_ as ThemePresetGallery, a$ as ThemePresetGalleryProps, b0 as ThemeToCssOptions, b1 as ThemeTokenMap, b2 as TimbalThemeIntent, b3 as TimbalThemePreset, b4 as TimbalThemePresetId, b5 as TimbalThemeStyle, b6 as TimbalThemeStyleProps, b7 as TimbalThemeTokens, b8 as applyThemePreset, b9 as applyTimbalTheme, ba as clearTimbalTheme, bb as connectionRowListClass, bc as createTimbalTheme, bd as getStoredThemePreset, be as getThemePreset, bf as themeToCss, bg as useAppCopilotContext, bh as useAppShellChat } from './chart-artifact-DWkqIAK5.cjs';
1
+ export { A as APP_KIT_AGENT_INSTRUCTIONS, a as AppChatPanel, b as AppChatPanelProps, c as AppConfirmDialog, d as AppConfirmDialogProps, e as AppCopilotContextValue, f as AppCopilotProvider, g as AppCopilotProviderProps, h as AppShell, i as AppShellChatControls, j as AppShellChatTrigger, k as AppShellChatTriggerProps, l as AppShellProps, m as AppShellTopbar, n as AppShellTopbarProps, B as BreadcrumbItem, o as Breadcrumbs, p as BreadcrumbsProps, C as CHART_PALETTE, q as ChartArtifactView, r as ChartLayout, s as ChartPanel, t as ChartPanelProps, u as ChartSeries, v as ChartVariant, w as ConnectionRow, x as ConnectionRowList, y as ConnectionRowListProps, z as ConnectionRowProps, D as DangerZone, E as DangerZoneAction, F as DangerZoneActionProps, G as DangerZoneProps, H as DataTable, I as DataTableColumn, J as DataTableProps, K as DataTableSort, L as DataTableSortDirection, M as DescriptionItem, N as DescriptionList, O as DescriptionListProps, P as EmptyState, Q as EmptyStateProps, R as ExpandableSection, S as ExpandableSectionProps, T as Field, U as FieldInput, V as FieldInputProps, W as FieldProps, X as FieldRow, Y as FieldRowProps, Z as FieldSelect, _ as FieldSelectProps, $ as FieldSwitch, a0 as FieldSwitchProps, a1 as FieldTextarea, a2 as FieldTextareaProps, a3 as FilterBar, a4 as FilterBarProps, a5 as FloatingUnsavedChangesBar, a6 as FloatingUnsavedChangesBarProps, a7 as FormSection, a8 as FormSectionProps, a9 as INTEGRATION_CATALOG_CARD_HEIGHT_CLASS, aa as InfoCard, ab as InfoCardProps, ac as InfoCardTone, ad as IntegrationCard, ae as IntegrationCardProps, af as IntegrationCardStatus, ag as IntegrationsEmptyState, ah as IntegrationsEmptyStateProps, ai as LineAreaChart, aj as LineAreaChartProps, ak as MetricChartCard, al as MetricChartCardProps, am as MetricChartMetric, an as MetricRow, ao as MetricRowItem, ap as MetricRowProps, aq as MetricTile, ar as MetricTileProps, as as Page, at as PageHeader, au as PageHeaderProps, av as PageProps, aw as PlanBadge, ax as PlanBadgeProps, ay as PlanBadgeTone, az as ResourceCard, aA as ResourceCardProps, aB as SearchInput, aC as SearchInputProps, aD as Section, aE as SectionProps, aF as SettingsSection, aG as SettingsSectionHeader, aH as SettingsSectionHeaderProps, aI as SettingsSectionProps, aJ as Sparkline, aK as SparklineProps, aL as StatTile, aM as StatTileProps, aN as StatusBadge, aO as StatusBadgeProps, aP as StatusBadgeTone, aQ as StatusDot, aR as StatusDotProps, aS as StatusDotTone, aT as SubNav, aU as SubNavItem, aV as SubNavProps, aW as SurfaceCard, aX as SurfaceCardProps, aY as THEME_AGENT_INSTRUCTIONS, aZ as TIMBAL_THEME_PRESETS, a_ as ThemePresetGallery, a$ as ThemePresetGalleryProps, b0 as ThemeShadow, b1 as ThemeToCssOptions, b2 as ThemeTokenMap, b3 as TimbalThemeIntent, b4 as TimbalThemePreset, b5 as TimbalThemePresetId, b6 as TimbalThemeStyle, b7 as TimbalThemeStyleProps, b8 as TimbalThemeTokens, b9 as TimbalThemeTypography, ba as applyThemePreset, bb as applyTimbalTheme, bc as clearTimbalTheme, bd as connectionRowListClass, be as createTimbalTheme, bf as ensureThemeFontLink, bg as getStoredThemePreset, bh as getThemePreset, bi as themeToCss, bj as useAppCopilotContext, bk as useAppShellChat } from './chart-artifact-BzcvblDe.cjs';
2
2
  export { B as Button } from './button-ClSgD6OF.cjs';
3
3
  export { C as ChartArtifact, T as ThreadVariant, a as TimbalChat, b as TimbalChatProps } from './chat-Bed4FQSl.cjs';
4
4
  import 'react';
package/dist/app.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- export { A as APP_KIT_AGENT_INSTRUCTIONS, a as AppChatPanel, b as AppChatPanelProps, c as AppConfirmDialog, d as AppConfirmDialogProps, e as AppCopilotContextValue, f as AppCopilotProvider, g as AppCopilotProviderProps, h as AppShell, i as AppShellChatControls, j as AppShellChatTrigger, k as AppShellChatTriggerProps, l as AppShellProps, m as AppShellTopbar, n as AppShellTopbarProps, B as BreadcrumbItem, o as Breadcrumbs, p as BreadcrumbsProps, C as CHART_PALETTE, q as ChartArtifactView, r as ChartLayout, s as ChartPanel, t as ChartPanelProps, u as ChartSeries, v as ChartVariant, w as ConnectionRow, x as ConnectionRowList, y as ConnectionRowListProps, z as ConnectionRowProps, D as DangerZone, E as DangerZoneAction, F as DangerZoneActionProps, G as DangerZoneProps, H as DataTable, I as DataTableColumn, J as DataTableProps, K as DataTableSort, L as DataTableSortDirection, M as DescriptionItem, N as DescriptionList, O as DescriptionListProps, P as EmptyState, Q as EmptyStateProps, R as ExpandableSection, S as ExpandableSectionProps, T as Field, U as FieldInput, V as FieldInputProps, W as FieldProps, X as FieldRow, Y as FieldRowProps, Z as FieldSelect, _ as FieldSelectProps, $ as FieldSwitch, a0 as FieldSwitchProps, a1 as FieldTextarea, a2 as FieldTextareaProps, a3 as FilterBar, a4 as FilterBarProps, a5 as FloatingUnsavedChangesBar, a6 as FloatingUnsavedChangesBarProps, a7 as FormSection, a8 as FormSectionProps, a9 as INTEGRATION_CATALOG_CARD_HEIGHT_CLASS, aa as InfoCard, ab as InfoCardProps, ac as InfoCardTone, ad as IntegrationCard, ae as IntegrationCardProps, af as IntegrationCardStatus, ag as IntegrationsEmptyState, ah as IntegrationsEmptyStateProps, ai as LineAreaChart, aj as LineAreaChartProps, ak as MetricChartCard, al as MetricChartCardProps, am as MetricChartMetric, an as MetricRow, ao as MetricRowItem, ap as MetricRowProps, aq as MetricTile, ar as MetricTileProps, as as Page, at as PageHeader, au as PageHeaderProps, av as PageProps, aw as PlanBadge, ax as PlanBadgeProps, ay as PlanBadgeTone, az as ResourceCard, aA as ResourceCardProps, aB as SearchInput, aC as SearchInputProps, aD as Section, aE as SectionProps, aF as SettingsSection, aG as SettingsSectionHeader, aH as SettingsSectionHeaderProps, aI as SettingsSectionProps, aJ as Sparkline, aK as SparklineProps, aL as StatTile, aM as StatTileProps, aN as StatusBadge, aO as StatusBadgeProps, aP as StatusBadgeTone, aQ as StatusDot, aR as StatusDotProps, aS as StatusDotTone, aT as SubNav, aU as SubNavItem, aV as SubNavProps, aW as SurfaceCard, aX as SurfaceCardProps, aY as THEME_AGENT_INSTRUCTIONS, aZ as TIMBAL_THEME_PRESETS, a_ as ThemePresetGallery, a$ as ThemePresetGalleryProps, b0 as ThemeToCssOptions, b1 as ThemeTokenMap, b2 as TimbalThemeIntent, b3 as TimbalThemePreset, b4 as TimbalThemePresetId, b5 as TimbalThemeStyle, b6 as TimbalThemeStyleProps, b7 as TimbalThemeTokens, b8 as applyThemePreset, b9 as applyTimbalTheme, ba as clearTimbalTheme, bb as connectionRowListClass, bc as createTimbalTheme, bd as getStoredThemePreset, be as getThemePreset, bf as themeToCss, bg as useAppCopilotContext, bh as useAppShellChat } from './chart-artifact-DwfRtQWL.js';
1
+ export { A as APP_KIT_AGENT_INSTRUCTIONS, a as AppChatPanel, b as AppChatPanelProps, c as AppConfirmDialog, d as AppConfirmDialogProps, e as AppCopilotContextValue, f as AppCopilotProvider, g as AppCopilotProviderProps, h as AppShell, i as AppShellChatControls, j as AppShellChatTrigger, k as AppShellChatTriggerProps, l as AppShellProps, m as AppShellTopbar, n as AppShellTopbarProps, B as BreadcrumbItem, o as Breadcrumbs, p as BreadcrumbsProps, C as CHART_PALETTE, q as ChartArtifactView, r as ChartLayout, s as ChartPanel, t as ChartPanelProps, u as ChartSeries, v as ChartVariant, w as ConnectionRow, x as ConnectionRowList, y as ConnectionRowListProps, z as ConnectionRowProps, D as DangerZone, E as DangerZoneAction, F as DangerZoneActionProps, G as DangerZoneProps, H as DataTable, I as DataTableColumn, J as DataTableProps, K as DataTableSort, L as DataTableSortDirection, M as DescriptionItem, N as DescriptionList, O as DescriptionListProps, P as EmptyState, Q as EmptyStateProps, R as ExpandableSection, S as ExpandableSectionProps, T as Field, U as FieldInput, V as FieldInputProps, W as FieldProps, X as FieldRow, Y as FieldRowProps, Z as FieldSelect, _ as FieldSelectProps, $ as FieldSwitch, a0 as FieldSwitchProps, a1 as FieldTextarea, a2 as FieldTextareaProps, a3 as FilterBar, a4 as FilterBarProps, a5 as FloatingUnsavedChangesBar, a6 as FloatingUnsavedChangesBarProps, a7 as FormSection, a8 as FormSectionProps, a9 as INTEGRATION_CATALOG_CARD_HEIGHT_CLASS, aa as InfoCard, ab as InfoCardProps, ac as InfoCardTone, ad as IntegrationCard, ae as IntegrationCardProps, af as IntegrationCardStatus, ag as IntegrationsEmptyState, ah as IntegrationsEmptyStateProps, ai as LineAreaChart, aj as LineAreaChartProps, ak as MetricChartCard, al as MetricChartCardProps, am as MetricChartMetric, an as MetricRow, ao as MetricRowItem, ap as MetricRowProps, aq as MetricTile, ar as MetricTileProps, as as Page, at as PageHeader, au as PageHeaderProps, av as PageProps, aw as PlanBadge, ax as PlanBadgeProps, ay as PlanBadgeTone, az as ResourceCard, aA as ResourceCardProps, aB as SearchInput, aC as SearchInputProps, aD as Section, aE as SectionProps, aF as SettingsSection, aG as SettingsSectionHeader, aH as SettingsSectionHeaderProps, aI as SettingsSectionProps, aJ as Sparkline, aK as SparklineProps, aL as StatTile, aM as StatTileProps, aN as StatusBadge, aO as StatusBadgeProps, aP as StatusBadgeTone, aQ as StatusDot, aR as StatusDotProps, aS as StatusDotTone, aT as SubNav, aU as SubNavItem, aV as SubNavProps, aW as SurfaceCard, aX as SurfaceCardProps, aY as THEME_AGENT_INSTRUCTIONS, aZ as TIMBAL_THEME_PRESETS, a_ as ThemePresetGallery, a$ as ThemePresetGalleryProps, b0 as ThemeShadow, b1 as ThemeToCssOptions, b2 as ThemeTokenMap, b3 as TimbalThemeIntent, b4 as TimbalThemePreset, b5 as TimbalThemePresetId, b6 as TimbalThemeStyle, b7 as TimbalThemeStyleProps, b8 as TimbalThemeTokens, b9 as TimbalThemeTypography, ba as applyThemePreset, bb as applyTimbalTheme, bc as clearTimbalTheme, bd as connectionRowListClass, be as createTimbalTheme, bf as ensureThemeFontLink, bg as getStoredThemePreset, bh as getThemePreset, bi as themeToCss, bj as useAppCopilotContext, bk as useAppShellChat } from './chart-artifact-Bl67kre7.js';
2
2
  export { B as Button } from './button-ClSgD6OF.js';
3
3
  export { C as ChartArtifact, T as ThreadVariant, a as TimbalChat, b as TimbalChatProps } from './chat-Bed4FQSl.js';
4
4
  import 'react';
package/dist/app.esm.js CHANGED
@@ -62,12 +62,13 @@ import {
62
62
  clearTimbalTheme,
63
63
  connectionRowListClass,
64
64
  createTimbalTheme,
65
+ ensureThemeFontLink,
65
66
  getStoredThemePreset,
66
67
  getThemePreset,
67
68
  themeToCss,
68
69
  useAppCopilotContext,
69
70
  useAppShellChat
70
- } from "./chunk-GBBLAM3G.esm.js";
71
+ } from "./chunk-6YVKCVEP.esm.js";
71
72
  import "./chunk-QIABF4KB.esm.js";
72
73
  import {
73
74
  CHART_PALETTE,
@@ -148,6 +149,7 @@ export {
148
149
  clearTimbalTheme,
149
150
  connectionRowListClass,
150
151
  createTimbalTheme,
152
+ ensureThemeFontLink,
151
153
  getStoredThemePreset,
152
154
  getThemePreset,
153
155
  themeToCss,