import { useAuth } from "@/contexts/auth-context"; import { useMantineColorScheme } from "@mantine/core"; import { useEffect, useRef } from "react"; import { getTheme } from "@/themes/registry"; import { resolveChromeColors } from "@/themes/chrome"; import { setBaseThemeColor } from "./theme-colors"; const ColorSchemeProvider = ({ children }: { children: React.ReactNode }) => { const { metadata: { colorScheme, theme }, } = useAuth(); const { colorScheme: currentScheme, setColorScheme } = useMantineColorScheme(); // Mantine recreates setColorScheme every render; calling it redundantly // triggers its global transition-suppression flash, so ref it and only // call on an actual value change. const setColorSchemeRef = useRef(setColorScheme); setColorSchemeRef.current = setColorScheme; const manifest = getTheme(theme); const forcedScheme = manifest.colorSchemes === "both" ? undefined : manifest.colorSchemes; useEffect(() => { const chrome = resolveChromeColors(manifest); if (forcedScheme) { setBaseThemeColor(chrome[forcedScheme].base); return; } if (!colorScheme) return; if (colorScheme !== currentScheme) { setColorSchemeRef.current(colorScheme); } const media = window.matchMedia("(prefers-color-scheme: dark)"); const applyThemeColor = () => { const resolved = colorScheme === "auto" ? media.matches ? "dark" : "light" : colorScheme; setBaseThemeColor(chrome[resolved].base); }; applyThemeColor(); if (colorScheme === "auto") { media.addEventListener("change", applyThemeColor); return () => media.removeEventListener("change", applyThemeColor); } }, [colorScheme, currentScheme, manifest, forcedScheme]); return children; }; export default ColorSchemeProvider;