Theme Editor Demo
Ecosistema completo para organización y gestión de contenido con interfaces espaciales
Theme Editor Demo Component
Overview
The ThemeEditorDemoComponent provides a user interface for exploring, editing, and creating themes using the application's theme system. It demonstrates how to interact with the theme system services to manage themes in the application.
Component Architecture
The component uses Angular's signals for state management and follows a reactive pattern with OnPush change detection for optimal performance. It implements:
- State Management: Uses signals to track themes, selections, and UI state
- Theme Normalization: Handles compatibility with legacy theme formats
- Real-time Preview: Updates theme in real-time as users make changes
- Performant Loading: Includes caching and throttling to prevent excessive operations
Key Services Used
- ThemeManagerService: For loading, applying, and saving themes
- ThemeApplicationService: For direct theme application to the DOM
Core Functionality
Theme Loading
The component loads themes on initialization with performance optimizations:
- Uses a throttling mechanism (5-second interval) to prevent excessive loads
- Caches themes for quicker access
- Defaults to the currently active theme when first loaded
loadThemes(): void {
// Skip redundant loads to improve performance
const now = Date.now();
if (now - this.lastLoadTime < this.LOAD_THROTTLE && this.cachedThemes.length > 0) {
// Use cached results if loaded recently
this.themes.set(this.cachedThemes);
// ...
return;
}
// Load themes from the theme manager
const themes = this.themeManager.availableThemes();
// ...
}
Theme Selection
When a user selects a theme:
- The selection is stored in both
selectedThemeandselectedThemeIdsignals - The theme is normalized to handle legacy formats
- The theme is applied to the application using
themeManager.applyTheme()
onThemeSelected(theme: Theme): void {
// Save the theme ID for selection
const themeId = theme.metadata?.id || theme.id;
this.selectedThemeId.set(themeId);
// Create a normalized theme object
const normalizedTheme = this.normalizeTheme(theme);
// Set the selected theme and apply it
this.selectedTheme.set(normalizedTheme);
this.themeManager.applyTheme(normalizedTheme).subscribe({...});
}
Theme Normalization
The component handles compatibility with different theme formats by normalizing legacy properties:
private normalizeTheme(theme: Theme): Theme {
// Create a copy to avoid modifying the original
const normalizedTheme: Theme = {
...theme,
colors: { ...theme.colors },
metadata: { ...theme.metadata }
};
// Map legacy color properties to the expected format
if (colorsAny.primaryColor && !colorsAny.primary) {
colorsAny.primary = colorsAny.primaryColor;
}
// ... similar mappings for other properties
return normalizedTheme;
}
Theme Editing
The editor supports both editing existing themes and creating new ones:
Edit Mode: Copies the selected theme to an editable model
onEditTheme(): void { const theme = this.selectedTheme(); this.editingTheme.set(true); this.isCreatingNew.set(false); // Initialize editable theme this.editableTheme = { id: theme.id, name: theme.metadata?.name || '', // ... other properties }; }Create Mode: Starts with a copy of the selected theme but assigns a new ID
onCreateTheme(): void { const baseTheme = this.selectedTheme(); const newId = crypto.randomUUID(); this.editableTheme = { id: newId, name: 'New Theme', // ... copies properties from base theme }; this.editingTheme.set(true); this.isCreatingNew.set(true); }
Real-time Preview
As users edit theme properties, changes are immediately previewed:
updateThemeColor(key: string, value: string): void {
this.editableTheme.colors = {
...this.editableTheme.colors,
[key]: value
};
// Preview the changes in real-time
this.previewTheme();
}
previewTheme(): void {
// Create a valid Theme object from our editable theme
const previewTheme: Theme = {
id: this.editableTheme.id,
// ... other properties
};
// Normalize and apply the theme for preview
const normalizedTheme = this.normalizeTheme(previewTheme);
this.themeManager.applyTheme(normalizedTheme).subscribe({...});
}
Theme Saving
When saving a theme:
- An editable model is converted back to a
Themeobject - The theme is normalized to ensure compatibility
- The theme is saved using
themeManager.saveTheme() - The theme list is refreshed and the new theme is applied
- The editor is closed
saveTheme(): void {
// Create a valid Theme object from our editable theme
const theme: Theme = {
id: this.editableTheme.id,
metadata: {
id: this.editableTheme.id,
name: this.editableTheme.name,
// ... other metadata
},
// ... other theme properties
};
// Normalize and save
const normalizedTheme = this.normalizeTheme(theme);
this.themeManager.saveTheme(normalizedTheme);
// Refresh, select and apply
this.loadThemes();
this.selectedTheme.set(normalizedTheme);
this.themeManager.applyTheme(normalizedTheme).subscribe({...});
// Close editor
this.editingTheme.set(false);
this.isCreatingNew.set(false);
}
UI Features
The component provides several UI helpers:
Theme Chip Styling: Displays theme chips with their primary color
getThemeChipStyle(theme: Theme): Record<string, string> { return { 'background-color': theme.colors.primary || '#5200ee' }; }Theme Identification: Shows first initial of theme name
getThemeInitial(theme: Theme): string { return theme.metadata.name.charAt(0).toUpperCase(); }Sample Style Preview: Shows how color changes affect components
getSampleStyles(): Record<string, string> { return { 'background-color': this.editableTheme.colors.background || '#ffffff', 'color': this.editableTheme.colors.onBackground || '#000000' }; }
Reactive State Management
The component uses Angular signals and computed values to manage state:
// State signals
themes = signal<Theme[]>([]);
selectedTheme = signal<Theme | null>(null);
editingTheme = signal<boolean>(false);
isCreatingNew = signal<boolean>(false);
// Computed values
showEditor = computed(() => !this.editingTheme());
isEditing = computed(() => this.editingTheme());
isCreating = computed(() => this.isCreatingNew());
Template Structure
The component's template includes sections for:
- Theme selection with visual indicators for the active theme
- Theme action buttons (create/edit)
- Theme editor interface with metadata and color inputs
- A color palette editor with real-time preview
- Preview section to see theme changes in context
Component Integration with Theme System
This component demonstrates the integration points with the theme system:
- Getting available themes:
themeManager.availableThemes() - Getting the active theme:
themeManager.activeTheme() - Applying a theme:
themeManager.applyTheme(theme) - Saving a theme:
themeManager.saveTheme(theme)
It also shows how to properly clean up subscriptions and handle theme normalization for backward compatibility.
Theme Editor Demo
This page documents the Theme Editor Demo and how it integrates with the theme system for real-time editing, preview, and persistence.
Source reference migrated from docs-to-review/theme-editor-demo-explanation.md with validation.
Architecture
- Standalone Angular component using signals and OnPush
- Integrates with
ThemeManagerServiceandThemeApplicationService
Core Flows
- Loading, selection, normalization, editing, preview, saving
Key Methods
onThemeSelected(theme)→ normalize + applyupdateThemeColor(key, value)→ preview via variables servicesaveTheme()→ validate, normalize, persist, apply
See code examples in the dev-tools library components.