import { useEffect, useRef } from "react"; import { App } from "../app"; import { applyDocumentTheme, applyHostFonts, applyHostStyleVariables, } from "../styles"; import { McpUiHostContext } from "../types"; /** * React hook that applies host style variables and theme as CSS custom properties. * * This hook listens to host context changes and automatically applies: * - `styles.variables` CSS variables to `document.documentElement` (e.g., `--color-background-primary`) * - `theme` via `color-scheme` CSS property, enabling `light-dark()` CSS function support * * The hook also applies styles and theme from the initial host context when * the app first connects. * * **Note:** If the host provides style values using CSS `light-dark()` function, * this hook ensures they work correctly by setting the `color-scheme` property * based on the host's theme preference. * * @param app - The connected {@link App} instance, or null during initialization * @param initialContext - Initial host context from the connection (optional). * If provided, styles and theme will be applied immediately on mount. * * @example * ```tsx * import { useApp, useHostStyleVariables } from '@modelcontextprotocol/ext-apps/react'; * * function MyApp() { * const { app, isConnected } = useApp({ * appInfo: { name: "MyApp", version: "1.0.0" }, * capabilities: {}, * }); * * // Apply host styles - pass initial context to apply styles from connect() immediately * useHostStyleVariables(app, app?.getHostContext()); * * return ( *
* Hello! *
* ); * } * ``` * * @see {@link applyHostStyleVariables} for the underlying styles function * @see {@link applyDocumentTheme} for the underlying theme function * @see {@link useHostFonts} for applying host fonts * @see {@link McpUiStyles} for available CSS variables */ export function useHostStyleVariables( app: App | null, initialContext?: McpUiHostContext | null, ): void { const initialApplied = useRef(false); // Apply initial styles and theme once on mount useEffect(() => { if (initialApplied.current) { return; } if (initialContext?.theme) { applyDocumentTheme(initialContext.theme); } if (initialContext?.styles?.variables) { applyHostStyleVariables(initialContext.styles.variables); } if (initialContext?.theme || initialContext?.styles?.variables) { initialApplied.current = true; } }, [initialContext]); // Listen for host context changes and apply updated styles/theme useEffect(() => { if (!app) { return; } app.onhostcontextchanged = (params) => { if (params.theme) { applyDocumentTheme(params.theme); } if (params.styles?.variables) { applyHostStyleVariables(params.styles.variables); } }; }, [app]); } /** * React hook that applies host fonts from CSS. * * This hook listens to host context changes and automatically applies: * - `styles.css.fonts` as a `