Live Preview
Ecosistema completo para organización y gestión de contenido con interfaces espaciales
Live Preview System
The Live Preview System provides real-time visual feedback for AI-generated Angular components with device simulation, theme switching, and export capabilities.
🎯 Purpose
Transform generated TypeScript/HTML/SCSS code into live, interactive Angular components with instant visual feedback - no manual compilation needed!
✨ Features
- 📱 Device Simulation - Preview on Mobile, Tablet, Desktop
- 🎨 Theme Switching - Test components with different themes
- 🔄 Hot Reload - Automatic updates when code changes
- 🔍 Scale Control - Zoom from 50% to 150%
Grid Overlay - Visual alignment guides
- 📏 Ruler Overlay - Measurement tools
- 📸 Image Export - Save previews as PNG
- ⛶ Fullscreen Mode - Maximize preview workspace
📦 Installation
The Live Preview System is part of @gograb-ai:
import { LivePreviewComponent, LivePreviewService } from '@gograb-ai';
🚀 Quick Start
Basic Usage
import { Component, inject } from '@angular/core';
import { LivePreviewComponent, LivePreviewService, GeneratedComponent } from '@gograb-ai';
@Component({
selector: 'my-app',
standalone: true,
imports: [LivePreviewComponent],
template: `
<lib-live-preview
[component]="previewComponent"
[showControls]="true">
</lib-live-preview>
`
})
export class MyComponent {
previewComponent: GeneratedComponent = {
id: 'btn-1',
name: 'SaveButton',
typescript: 'export class SaveButton { }',
html: '<button>Save</button>',
scss: '.button { color: blue; }'
};
}
Programmatic Usage
import { inject } from '@angular/core';
import { LivePreviewService, GeneratedComponent } from '@gograb-ai';
export class MyService {
private preview = inject(LivePreviewService);
async previewComponent(): Promise<void> {
const component: GeneratedComponent = {
id: 'component-1',
name: 'MyComponent',
typescript: '...',
html: '...',
scss: '...'
};
await this.preview.loadComponent(component);
}
}
🎨 Component API
LivePreviewComponent
Inputs
@Input() component: GeneratedComponent | null; // Component to preview
@Input() showControls: boolean = true; // Show control panel
@Input() enableHotReload: boolean = false; // Enable hot reload
Properties
readonly selectedDevice: Signal<DeviceType>; // Current device
readonly selectedTheme: Signal<string>; // Current theme
readonly scale: Signal<number>; // Current scale
readonly showGrid: Signal<boolean>; // Grid visibility
readonly showRuler: Signal<boolean>; // Ruler visibility
readonly isFullscreen: Signal<boolean>; // Fullscreen state
Methods
loadComponent(component: GeneratedComponent): Promise<void>
reload(): Promise<void>
changeDevice(device: DeviceType): void
changeTheme(theme: string): void
changeScale(scale: number): void
toggleGrid(): void
toggleRuler(): void
toggleFullscreen(): void
exportImage(): Promise<void>
clear(): void
🛠️ Service API
LivePreviewService
Properties
readonly isLoading: Signal<boolean>;
readonly error: Signal<string | null>;
readonly currentDevice: Signal<DeviceType>;
readonly deviceDimensions: Signal<DeviceDimensions>;
readonly previewStyles: Signal<PreviewStyles>;
readonly hotReloadEnabled: Signal<boolean>;
Methods
// Load component for preview
loadComponent(component: GeneratedComponent): Promise<void>
// Set rendering container
setContainer(container: ViewContainerRef): void
// Device controls
setDevice(device: DeviceType): void
// Theme controls
setTheme(theme: string): void
// Scale controls
setScale(scale: number): void
// Overlay controls
toggleGrid(): void
toggleRuler(): void
// Hot reload
enableHotReload(): void
disableHotReload(): void
reload(): Promise<void>
// Export
exportAsImage(): Promise<Blob>
// Statistics
getStats(): PreviewStats
// Cleanup
clear(): void
📱 Device Types
enum DeviceType {
MOBILE = 'mobile', // 375x667 (iPhone SE)
TABLET = 'tablet', // 768x1024 (iPad)
DESKTOP = 'desktop', // 1920x1080
FULL = 'full' // Full viewport
}
🎨 Integration with AI Generation
With Intelligence Coordinator
import { Component, inject, signal } from '@angular/core';
import { IntelligenceCoordinatorService, LivePreviewComponent } from '@gograb-ai';
@Component({
selector: 'ai-generator',
standalone: true,
imports: [LivePreviewComponent],
template: `
<button (click)="generate()">Generate & Preview</button>
@if (previewComponent()) {
<lib-live-preview [component]="previewComponent()"></lib-live-preview>
}
`
})
export class AIGeneratorComponent {
private coordinator = inject(IntelligenceCoordinatorService);
readonly previewComponent = signal<GeneratedComponent | null>(null);
async generate(): Promise<void> {
this.coordinator.coordinateGeneration({
type: 'component',
description: 'Create a user profile card',
// ... config
}).subscribe(result => {
this.previewComponent.set({
id: result.metadata.id,
name: 'ProfileCard',
typescript: result.code.componentTs,
html: result.code.componentHtml,
scss: result.code.componentScss
});
});
}
}
With QuickGenerate
import { QuickGenerate } from '@gograb-ai';
// Generate and preview in one go
const button = await QuickGenerate.button('Save Changes');
await QuickGenerate.livePreview(button);
🎯 Advanced Usage
Custom Device Configuration
// Coming soon: Custom device presets
Theme Integration
import { inject } from '@angular/core';
import { LivePreviewService } from '@gograb-ai';
import { ThemeManagerService } from '@theme-runtime';
export class MyComponent {
private preview = inject(LivePreviewService);
private themeManager = inject(ThemeManagerService);
switchTheme(theme: string): void {
this.preview.setTheme(theme);
this.themeManager.setTheme(theme);
}
}
Hot Reload
import { inject } from '@angular/core';
import { LivePreviewService } from '@gograb-ai';
export class DevelopmentComponent {
private preview = inject(LivePreviewService);
enableDevelopmentMode(): void {
this.preview.enableHotReload();
console.log('Hot reload enabled');
}
}
📊 Statistics & Monitoring
import { inject } from '@angular/core';
import { LivePreviewService } from '@gograb-ai';
export class MonitoringComponent {
private preview = inject(LivePreviewService);
checkStats(): void {
const stats = this.preview.getStats();
console.log('Preview stats:', {
isLoaded: stats.isLoaded,
componentName: stats.componentName,
hotReloadEnabled: stats.hotReloadEnabled,
lastReload: new Date(stats.lastReload)
});
}
}
🎨 Styling & Theming
The Live Preview Component automatically inherits theme variables from the @theme-system:
// Custom preview styles
.live-preview {
--preview-bg: var(--surface-color);
--preview-border: var(--border-color);
--preview-control-bg: var(--panel-bg);
}
🔧 Configuration
Control Panel Options
<lib-live-preview
[component]="myComponent"
[showControls]="true" // Show/hide controls
[enableHotReload]="false"> // Enable hot reload
</lib-live-preview>
Device Presets
The system provides 3 built-in device presets:
- Mobile: 375x667px (iPhone SE)
- Tablet: 768x1024px (iPad)
- Desktop: 1920x1080px (Standard HD)
⚠️ Limitations
- Dynamic component compilation requires runtime compilation support
- Some Angular features may not work in preview (e.g., routing)
- External dependencies must be pre-loaded
- Custom decorators may not compile correctly
🐛 Troubleshooting
Component Not Loading
// Check for compilation errors
this.preview.error().subscribe(err => {
if (err) {
console.error('Preview error:', err);
}
});
Theme Not Applying
Ensure ThemeManagerService is initialized:
import { ThemeManagerService } from '@theme-runtime';
constructor(private themeManager: ThemeManagerService) {
this.themeManager.initializeTheme();
}
Hot Reload Not Working
Hot reload requires manual reload calls:
this.preview.enableHotReload();
// After code changes
await this.preview.reload();
📚 Related Documentation
🎯 Best Practices
- Always Handle Errors: Monitor the
errorsignal - Clear on Destroy: Call
clear()inngOnDestroy - Use Signals: Leverage reactive signals for state
- Device Testing: Test on all device sizes
- Theme Testing: Verify all theme variants
- Performance: Disable hot reload in production
🚀 Future Enhancements
- Custom device presets
- Split-screen comparison mode
- A/B testing support
- Screenshot annotations
- Video recording
- Collaborative preview
- Performance metrics overlay
💡 Examples
Example 1: Basic Preview
@Component({
selector: 'basic-preview-example',
standalone: true,
imports: [LivePreviewComponent],
template: `
<lib-live-preview [component]="component"></lib-live-preview>
`
})
export class BasicPreviewExample {
component: GeneratedComponent = {
id: 'example-1',
name: 'HelloWorld',
typescript: `
import { Component } from '@angular/core';
@Component({
selector: 'hello-world',
template: '<h1>Hello, World!</h1>',
styles: ['h1 { color: blue; }']
})
export class HelloWorldComponent {}
`,
html: '<h1>Hello, World!</h1>',
scss: 'h1 { color: blue; }'
};
}
Example 2: With Controls
@Component({
selector: 'advanced-preview-example',
standalone: true,
imports: [LivePreviewComponent, CommonModule],
template: `
<div class="controls">
<button (click)="loadButton()">Load Button</button>
<button (click)="loadCard()">Load Card</button>
<button (click)="clear()">Clear</button>
</div>
@if (currentComponent()) {
<lib-live-preview
[component]="currentComponent()"
[showControls]="true"
[enableHotReload]="isDev()">
</lib-live-preview>
}
`
})
export class AdvancedPreviewExample {
private preview = inject(LivePreviewService);
readonly currentComponent = signal<GeneratedComponent | null>(null);
readonly isDev = signal(true);
loadButton(): void {
this.currentComponent.set({
id: 'btn-1',
name: 'SaveButton',
typescript: '...',
html: '<button>Save</button>',
scss: 'button { padding: 1rem; }'
});
}
loadCard(): void {
this.currentComponent.set({
id: 'card-1',
name: 'UserCard',
typescript: '...',
html: '<div class="card">...</div>',
scss: '.card { border-radius: 8px; }'
});
}
clear(): void {
this.currentComponent.set(null);
this.preview.clear();
}
}
📞 Support
For issues, feature requests, or questions:
- Create an issue in the repository
- Check existing documentation
- Review example implementations
Last Updated: 2025-01-10 Version: 1.0.0 Status: ✅ Production Ready