import * as React from "react" export type Agents24ChatAppearance = "system" | "light" | "dark" export type Agents24ChatTheme = "soft" | "sharp" export type Agents24ChatAppearanceController = { appearance: Agents24ChatAppearance setAppearance: (appearance: Agents24ChatAppearance) => void } type ThemeContextValue = { inherited: boolean appearance: Agents24ChatAppearance portalContainer: HTMLElement | null setAppearance: (appearance: Agents24ChatAppearance) => void } const ThemeContext = React.createContext(null) const appearanceEvent = "agents24-chat-appearance-change" const subscribeAppearance = (notify: () => void) => { window.addEventListener("storage", notify) window.addEventListener(appearanceEvent, notify) return () => { window.removeEventListener("storage", notify) window.removeEventListener(appearanceEvent, notify) } } const subscribeDarkMode = (notify: () => void) => { const media = window.matchMedia?.("(prefers-color-scheme: dark)") media?.addEventListener("change", notify) return () => media?.removeEventListener("change", notify) } const getDarkMode = () => window.matchMedia?.("(prefers-color-scheme: dark)").matches ?? false const storageKey = "agents24-chat-appearance" function storedAppearance(): Agents24ChatAppearance { try { const stored = window.localStorage.getItem(storageKey) return stored === "light" || stored === "dark" || stored === "system" ? stored : "system" } catch { return "system" } } export function ThemeProvider({ children, controller, theme = "soft", mode = "isolated", }: { children: React.ReactNode controller?: Agents24ChatAppearanceController theme?: Agents24ChatTheme mode?: "isolated" | "inherit" }) { const [sessionAppearance, setSessionAppearance] = React.useState(null) const stored = React.useSyncExternalStore(subscribeAppearance, storedAppearance, () => "system" as const) const systemDark = React.useSyncExternalStore(subscribeDarkMode, getDarkMode, () => false) const [portalContainer, setPortalContainer] = React.useState(null) const appearance = controller?.appearance ?? sessionAppearance ?? stored const resolvedAppearance = appearance === "system" ? (systemDark ? "dark" : "light") : appearance const change = React.useCallback((next: Agents24ChatAppearance) => { if (controller) { controller.setAppearance(next) return } setSessionAppearance(next) try { window.localStorage.setItem(storageKey, next) } catch { /* storage is optional */ } window.dispatchEvent(new Event(appearanceEvent)) }, [controller]) return (
{children}
) } export function useTheme() { const context = React.useContext(ThemeContext) if (!context) throw new Error("useTheme must be used inside ThemeProvider") return context } export function useThemePortalContainer() { return useTheme().portalContainer }