1import { HTML_RENDER_DEFAULT_FONTS, htmlRenderTheme } from "@t3tools/shared/htmlRender";
2import { useMemo, useSyncExternalStore } from "react";
3
4import { appearanceFontStack } from "../appearanceFonts";
5import {
6 getStandardThemeColors,
7 getThemeColorsForMode,
8 getThemeDefinition,
9 resolveThemeHalf,
10 subscribeToCustomThemes,
11 themeColorToHex,
12 type ThemeAppearance,
13 type ThemeHalves,
14 type ThemePreference,
15} from "../themePalette";
16import { useClientSettings } from "./useSettings";
17import { useTheme } from "./useTheme";
18
19/** The palette `applyTheme` paints for a preference, or the stock look when no theme applies. */
20function resolveActiveThemeColors(
21 theme: ThemePreference,
22 halves: ThemeHalves | null,
23 appearance: ThemeAppearance,
24) {
25 const definition = getThemeDefinition(resolveThemeHalf(theme, halves, appearance));
26 return definition === null
27 ? getStandardThemeColors(appearance)
28 : (getThemeColorsForMode(definition, appearance) ?? definition.colors);
29}
30
31/** The app's active theme and fonts, as handed to agent HTML renders. Stable until one changes. */
32export function useHtmlRenderTheme() {
33 const { theme, resolvedTheme, themeHalves } = useTheme();
34 // Custom and published palettes can be edited in place, under an unchanged preference.
35 const colors = useSyncExternalStore(
36 subscribeToCustomThemes,
37 () => resolveActiveThemeColors(theme, themeHalves, resolvedTheme),
38 () => getStandardThemeColors(resolvedTheme),
39 );
40 const sans = useClientSettings((settings) => settings.fontFamilySans);
41 const mono = useClientSettings((settings) => settings.fontFamilyCode);
42 return useMemo(
43 () =>
44 htmlRenderTheme(
45 Object.fromEntries(
46 Object.entries(colors).map(([role, color]) => [role, themeColorToHex(color) ?? color]),
47 ) as typeof colors,
48 resolvedTheme,
49 {
50 sans: appearanceFontStack(sans, HTML_RENDER_DEFAULT_FONTS.sans),
51 mono: appearanceFontStack(mono, HTML_RENDER_DEFAULT_FONTS.mono),
52 },
53 ),
54 [colors, resolvedTheme, sans, mono],
55 );
56}