/** * Isomorphic theme metadata. * * Deliberately framework-free: it is imported from server code (project * theme validation in lib/actions/projects.ts, the no-FOUC script rendered * by the project page) *and* client code (theme provider, pickers), so it * must stay free of React/DOM imports. What *applies* themes to the DOM * lives in components/theme/theme-provider.tsx; the display options * (labels, icons, swatches) live in components/theme/theme-toggle.tsx. */ /* Order is the picker order: all the light looks, then the dark looks. */ export const THEMES = [ "default", "sunset", "meadow", "honey", "rose", "lavender", "slate", "blueprint", "vaporwave", "notebook", "dark", "ocean", "pine", "plum", "midnight", "ember", "rosewood", "cyberpunk", "starfield", ] as const; export type ThemeName = (typeof THEMES)[number]; export type RawTheme = ThemeName | "system"; /** Theme name -> class applied to (see app/globals.css). */ export const THEME_CLASSES: Record = { default: "theme-default", sunset: "theme-sunset", meadow: "theme-meadow", honey: "theme-honey", rose: "theme-rose", lavender: "theme-lavender", slate: "theme-slate", blueprint: "theme-blueprint", vaporwave: "theme-vaporwave", notebook: "theme-notebook", dark: "dark", ocean: "ocean", pine: "theme-pine", plum: "theme-plum", midnight: "theme-midnight", ember: "theme-ember", rosewood: "theme-rosewood", cyberpunk: "theme-cyberpunk", starfield: "theme-starfield", }; /** Themes whose *surfaces* are dark (see app/globals.css). The single source * of truth for every dark-surface check: isDarkTheme, the sonner toaster, * color-scheme, and the `dark:` custom-variant in globals.css. */ export const DARK_SURFACES: ThemeName[] = [ "dark", "ocean", "pine", "plum", "midnight", "ember", "rosewood", "cyberpunk", "starfield", ]; export function themeColorScheme(name: ThemeName): "light" | "dark" { return DARK_SURFACES.includes(name) ? "dark" : "light"; } /** * Inline-script source that switches over to `theme` immediately * (before first paint), the same way the global no-FOUC script in * app/layout.tsx works, and leaves a `data-project-theme` marker behind so * the ThemeProvider can pick the theme up as its initial scope at * hydration. Render it from a server component with * `dangerouslySetInnerHTML`. */ export function themeSwitchScript(theme: ThemeName): string { const classes = JSON.stringify([ ...Object.values(THEME_CLASSES), "light", ]); return `try{var r=document.documentElement;var c=${classes};for(var i=0;i