• Provides theme context to its children, managing theme state and updates.

    Parameters

    • children: Readonly<{ children: ReactNode }>

      The React children to be wrapped by the provider.

    Returns Element

    The theme context provider with value for consumers.

    export function ThemeProvider({
    children,
    }: Readonly<{ children: React.ReactNode }>) {
    const [theme, setTheme] = useState<ThemePreferences>({
    system: "light",
    local: null,
    });
    const [isDarkMode, setIsDarkMode] = useState(false);
    const { registerStateInspector: registerThemeStateInspector } = useDebug();
    const themeInspectorHandleRef =
    useRef<StateInspectorHandle<ThemeDebugSnapshot> | null>(null);
    const themeSnapshotRef = useRef<ThemeDebugSnapshot | null>(null);
    const getThemeSnapshotRef = useRef<() => ThemeDebugSnapshot>(() => ({
    theme,
    isDarkMode,
    }));
    getThemeSnapshotRef.current = () => ({
    theme,
    isDarkMode,
    });

    const emitThemeSnapshot = useCallback(() => {
    if (!themeInspectorHandleRef.current) return;
    const snapshot = getThemeSnapshotRef.current();
    themeSnapshotRef.current = snapshot;
    themeInspectorHandleRef.current.publish(snapshot);
    }, []);

    const applyThemeDebugSnapshot = useCallback(
    (snapshot: ThemeDebugSnapshot) => {
    setTheme((prev) => ({
    system: snapshot.theme?.system ?? prev.system,
    local: snapshot.theme?.local ?? prev.local,
    }));

    const computedIsDark = (() => {
    if (typeof snapshot.isDarkMode === "boolean")
    return snapshot.isDarkMode;
    if (snapshot.theme?.local === "dark") return true;
    if (snapshot.theme?.local === "light") return false;
    return undefined;
    })();

    if (computedIsDark !== undefined) {
    setIsDarkMode(computedIsDark);
    }

    const resolvedMode =
    snapshot.theme?.local ?? (computedIsDark ? "dark" : "light");
    if (resolvedMode === "dark" || resolvedMode === "light") {
    updateDocumentTheme(resolvedMode);
    }
    },
    [],
    );

    const initializeTheme = useCallback(async () => {
    try {
    const currentTheme = await getCurrentTheme();
    setTheme(currentTheme);

    // Add null check before accessing local property
    const mode = currentTheme?.local || currentTheme?.system || "light";
    let resolvedMode: "dark" | "light";
    if (mode === "dark" || mode === "light") {
    resolvedMode = mode;
    } else {
    // Resolve system mode to dark/light explicitly
    resolvedMode = (await globalThis.themeMode.system()) ? "dark" : "light";
    }
    const isDark = resolvedMode === "dark";
    setIsDarkMode(isDark);
    updateDocumentTheme(resolvedMode);
    } catch (error) {
    console.error("Failed to initialize theme:", error);
    // Fallback to light theme
    setTheme({ system: "light", local: "light" });
    setIsDarkMode(false);
    updateDocumentTheme("light");
    }
    }, []);

    useEffect(() => {
    initializeTheme();

    // Set up event listener for theme changes from other components
    const handleThemeChange = async () => {
    const currentTheme = await getCurrentTheme();
    setTheme(currentTheme);
    setIsDarkMode(currentTheme.local === "dark");
    };

    document.addEventListener("themeToggled", handleThemeChange);
    return () => {
    document.removeEventListener("themeToggled", handleThemeChange);
    };
    }, [initializeTheme]);

    useEffect(() => {
    emitThemeSnapshot();
    }, [theme, isDarkMode, emitThemeSnapshot]);

    useEffect(() => {
    if (!registerThemeStateInspector) return;

    themeSnapshotRef.current = getThemeSnapshotRef.current();

    const handle = registerThemeStateInspector<ThemeDebugSnapshot>({
    id: "theme-state",
    label: "Theme",
    description:
    "Current theme preferences and resolved dark mode flag applied to the document.",
    group: "Application",
    getSnapshot: () =>
    themeSnapshotRef.current ?? getThemeSnapshotRef.current(),
    setSnapshot: applyThemeDebugSnapshot,
    });

    themeInspectorHandleRef.current = handle;

    return () => {
    handle.unregister();
    themeInspectorHandleRef.current = null;
    themeSnapshotRef.current = null;
    };
    }, [registerThemeStateInspector, applyThemeDebugSnapshot]);

    const setThemeMode = async (mode: ThemeMode) => {
    let newIsDarkMode: boolean;
    if (mode === "dark") {
    newIsDarkMode = await enableDarkMode();
    } else if (mode === "light") {
    newIsDarkMode = await enableLightMode();
    } else {
    newIsDarkMode = await applySystemTheme();
    }
    setTheme(await getCurrentTheme());
    setIsDarkMode(newIsDarkMode);
    return newIsDarkMode;
    };

    const toggleTheme = async () => {
    // If current theme is dark or not set, switch to light, otherwise switch to dark
    const newTheme = theme.local === "dark" ? "light" : "dark";
    return await setThemeMode(newTheme);
    };

    const contextValue = React.useMemo(
    () => ({ theme, isDarkMode, setThemeMode, toggleTheme }),
    [theme, isDarkMode, setThemeMode, toggleTheme],
    );

    return (
    <ThemeContext.Provider value={contextValue}>
    {children}
    </ThemeContext.Provider>
    );
    }