themes lol

This commit is contained in:
2026-08-23 17:17:04 -07:00
parent 0a7b5fa00f
commit 6f575d6a23
79 changed files with 13108 additions and 278 deletions
+37
View File
@@ -0,0 +1,37 @@
import type { ThemeManifest } from "./types";
// Themes are auto-discovered: each src/themes/<id>/manifest.ts default-export
// is registered here. Keep this module CSS-free so server fns can import it;
// theme stylesheets are aggregated separately in ./styles.ts.
const modules = import.meta.glob<{ default: ThemeManifest }>("./*/manifest.ts", {
eager: true,
});
export const THEMES: Record<string, ThemeManifest> = {};
for (const [path, mod] of Object.entries(modules)) {
const folder = path.split("/")[1];
const manifest = mod.default;
if (!manifest || manifest.id !== folder) {
console.warn(`[themes] skipping ${path}: manifest id must equal folder name`);
continue;
}
THEMES[manifest.id] = manifest;
}
export const DEFAULT_THEME_ID = "default";
if (!THEMES[DEFAULT_THEME_ID]) {
throw new Error("[themes] default theme manifest is missing or invalid");
}
export const THEME_IDS = Object.keys(THEMES);
// Base order: default first, rest by id. Pickers re-sort by LOCALIZED title
// at render time (labels are i18n descriptors, unresolvable here).
export const THEME_LIST: ThemeManifest[] = Object.values(THEMES).sort(
(a, b) => (a.order ?? 100) - (b.order ?? 100) || a.id.localeCompare(b.id)
);
export const getTheme = (id?: string | null): ThemeManifest =>
(id ? THEMES[id] : undefined) ?? THEMES[DEFAULT_THEME_ID];