|
|
@@ -30,7 +30,7 @@ const DEFAULT_THEME = {
|
|
|
headingFontFamily: 'Inter, system-ui, sans-serif',
|
|
|
fontSize: {
|
|
|
xs: '0.75rem',
|
|
|
- sm: '0.875rem',
|
|
|
+ sm: '0.875rem',
|
|
|
base: '1rem',
|
|
|
lg: '1.125rem',
|
|
|
xl: '1.25rem',
|
|
|
@@ -48,7 +48,7 @@ const DEFAULT_THEME = {
|
|
|
layout: {
|
|
|
borderRadius: {
|
|
|
sm: '0.125rem',
|
|
|
- base: '0.25rem',
|
|
|
+ base: '0.25rem',
|
|
|
md: '0.375rem',
|
|
|
lg: '0.5rem',
|
|
|
xl: '0.75rem',
|
|
|
@@ -179,11 +179,19 @@ async function saveThemes(themesData) {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+import { getActiveThemeId, setActiveThemeId } from './config.js';
|
|
|
+
|
|
|
+// ... existing imports ...
|
|
|
+
|
|
|
+// ... (keep constants and loadThemes/saveThemes as is, but remove activeTheme from their logic if possible,
|
|
|
+// strictly speaking we just need to ensure getActiveTheme/setActiveTheme use the new system)
|
|
|
+
|
|
|
// Get all themes (built-in + custom)
|
|
|
export async function getAllThemes() {
|
|
|
const data = await loadThemes();
|
|
|
+ const activeThemeId = await getActiveThemeId();
|
|
|
return {
|
|
|
- activeTheme: data.activeTheme,
|
|
|
+ activeTheme: activeThemeId,
|
|
|
themes: [...data.builtInThemes, ...data.customThemes]
|
|
|
};
|
|
|
}
|
|
|
@@ -191,69 +199,69 @@ export async function getAllThemes() {
|
|
|
// Get active theme
|
|
|
export async function getActiveTheme() {
|
|
|
const data = await loadThemes();
|
|
|
+ const activeThemeId = await getActiveThemeId();
|
|
|
const allThemes = [...data.builtInThemes, ...data.customThemes];
|
|
|
- return allThemes.find(theme => theme.id === data.activeTheme) || DEFAULT_THEME;
|
|
|
+ return allThemes.find(theme => theme.id === activeThemeId) || DEFAULT_THEME;
|
|
|
}
|
|
|
|
|
|
// Set active theme
|
|
|
export async function setActiveTheme(themeId) {
|
|
|
const data = await loadThemes();
|
|
|
const allThemes = [...data.builtInThemes, ...data.customThemes];
|
|
|
-
|
|
|
+
|
|
|
if (!allThemes.find(theme => theme.id === themeId)) {
|
|
|
throw new Error('Theme not found');
|
|
|
}
|
|
|
-
|
|
|
- data.activeTheme = themeId;
|
|
|
- await saveThemes(data);
|
|
|
-
|
|
|
+
|
|
|
+ await setActiveThemeId(themeId);
|
|
|
+
|
|
|
return allThemes.find(theme => theme.id === themeId);
|
|
|
}
|
|
|
|
|
|
// Create custom theme
|
|
|
export async function createCustomTheme(themeData) {
|
|
|
const data = await loadThemes();
|
|
|
-
|
|
|
+
|
|
|
// Validate required fields
|
|
|
if (!themeData.name || !themeData.id) {
|
|
|
throw new Error('Theme name and id are required');
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
// Check if theme ID already exists
|
|
|
const allThemes = [...data.builtInThemes, ...data.customThemes];
|
|
|
if (allThemes.find(theme => theme.id === themeData.id)) {
|
|
|
throw new Error('Theme ID already exists');
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
const newTheme = {
|
|
|
...DEFAULT_THEME,
|
|
|
...themeData,
|
|
|
createdAt: new Date().toISOString(),
|
|
|
isBuiltIn: false
|
|
|
};
|
|
|
-
|
|
|
+
|
|
|
data.customThemes.push(newTheme);
|
|
|
await saveThemes(data);
|
|
|
-
|
|
|
+
|
|
|
return newTheme;
|
|
|
}
|
|
|
|
|
|
// Update custom theme
|
|
|
export async function updateCustomTheme(themeId, themeData) {
|
|
|
const data = await loadThemes();
|
|
|
-
|
|
|
+
|
|
|
const themeIndex = data.customThemes.findIndex(theme => theme.id === themeId);
|
|
|
if (themeIndex === -1) {
|
|
|
throw new Error('Custom theme not found');
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
data.customThemes[themeIndex] = {
|
|
|
...data.customThemes[themeIndex],
|
|
|
...themeData,
|
|
|
id: themeId, // Prevent ID changes
|
|
|
updatedAt: new Date().toISOString()
|
|
|
};
|
|
|
-
|
|
|
+
|
|
|
await saveThemes(data);
|
|
|
return data.customThemes[themeIndex];
|
|
|
}
|
|
|
@@ -261,17 +269,18 @@ export async function updateCustomTheme(themeId, themeData) {
|
|
|
// Delete custom theme
|
|
|
export async function deleteCustomTheme(themeId) {
|
|
|
const data = await loadThemes();
|
|
|
-
|
|
|
+
|
|
|
const themeIndex = data.customThemes.findIndex(theme => theme.id === themeId);
|
|
|
if (themeIndex === -1) {
|
|
|
throw new Error('Custom theme not found');
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
// If this was the active theme, switch to default
|
|
|
- if (data.activeTheme === themeId) {
|
|
|
- data.activeTheme = 'default';
|
|
|
+ const activeThemeId = await getActiveThemeId();
|
|
|
+ if (activeThemeId === themeId) {
|
|
|
+ await setActiveThemeId('default');
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
data.customThemes.splice(themeIndex, 1);
|
|
|
await saveThemes(data);
|
|
|
}
|
|
|
@@ -281,11 +290,11 @@ export async function exportTheme(themeId) {
|
|
|
const data = await loadThemes();
|
|
|
const allThemes = [...data.builtInThemes, ...data.customThemes];
|
|
|
const theme = allThemes.find(theme => theme.id === themeId);
|
|
|
-
|
|
|
+
|
|
|
if (!theme) {
|
|
|
throw new Error('Theme not found');
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
// Remove internal fields for export
|
|
|
const { createdAt, updatedAt, isBuiltIn, ...exportData } = theme;
|
|
|
return exportData;
|