theme-o-rama
Version:
A TypeScript library for dynamic theme management in react + shadcn + tailwind applications
70 lines (69 loc) • 2.62 kB
JavaScript
import { ThemeCache } from "./theme-cache.js";
import { validateTheme } from "./theme-schema-validation.js";
import { deepMerge } from "./utils.js";
export class ThemeLoader {
constructor() {
this.themesCache = new ThemeCache();
}
clearCache() {
this.themesCache.invalidate();
}
getTheme(themeName) {
return this.themesCache.getThemeSafe(themeName);
}
getThemes() {
return this.themesCache.getThemes();
}
async loadThemes(themes, imageResolver = null) {
await Promise.all(themes.map((theme) => this.loadTheme(theme, imageResolver)));
}
async loadTheme(theme, imageResolver = null) {
try {
// Create a deep copy of the theme to avoid readonly issues
const workingTheme = await this.initializeTheme(JSON.parse(JSON.stringify(theme)), imageResolver);
this.themesCache.addTheme(workingTheme);
}
catch (error) {
console.error(`Error loading theme`, error);
}
}
async loadThemeFromJson(themeJson, imageResolver = null) {
const theme = validateTheme(themeJson);
const initializeTheme = await this.initializeTheme(theme, imageResolver);
this.themesCache.addTheme(initializeTheme);
return initializeTheme;
}
async initializeTheme(theme, imageResolver = null) {
try {
if (theme.inherits) {
const inheritedTheme = this.themesCache.getThemeSafe(theme.inherits);
const tags = theme.tags || [];
theme = deepMerge(inheritedTheme, theme);
theme.tags = tags;
}
if (theme.backgroundImage && imageResolver) {
try {
// we allow remote urls and local files for built in themes
// local images get imported from the theme's folder
if (urlRequiresResolution(theme.backgroundImage)) {
theme.backgroundImage = await imageResolver(theme.name, theme.backgroundImage);
}
}
catch (error) {
console.warn(`Error loading background image for theme ${theme.name}:`, error);
theme.backgroundImage = undefined;
}
}
}
catch (error) {
console.error(`Error loading theme`, error);
}
return theme;
}
}
function urlRequiresResolution(url) {
return !!(url &&
!url.startsWith("http://") &&
!url.startsWith("https://") &&
!url.startsWith("data:"));
}