"use client"; import { useEffect, useState } from "react"; import { useTheme, resolveTheme } from "./theme-provider"; // The themes whose *surfaces* are dark (see app/globals.css): "dark" and // "ocean". Anything that used to compare `resolvedTheme === "dark"` to pick // a color variant (group card fills/strokes, markdown widget color modes, // ...) uses this instead, so Ocean is treated exactly like Dark. const DARK_SURFACES = new Set(["dark", "ocean"]); function useMounted(): boolean { const [mounted, setMounted] = useState(false); useEffect(() => { setMounted(true); }, []); return mounted; } /** * True when the active theme has dark surfaces (Dark or Ocean). * * Reactive to UI theme switches: the value is derived from the provider's * theme state (the single source of truth), so the moment `setTheme` fires, * every consumer re-renders with the new variant in the same commit -- no * stale card colors, no manual refresh needed. * * Hydration-safe: until mounted we always report "light", matching the * server render (the no-FOUC script in app/layout.tsx covers the CSS side * of that first frame). */ export function isDarkTheme(): boolean { const mounted = useMounted(); const { theme } = useTheme(); if (!mounted) return false; return DARK_SURFACES.has(resolveTheme(theme)); } /** * The `data-color-mode` value the markdown editor/preview widgets expect. * They only understand light/dark, so the light "sunset" look reports as * light and the dark "ocean" look reports as dark. */ export function colorModeFromTheme(): "light" | "dark" { return isDarkTheme() ? "dark" : "light"; }