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

📦 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:

⚠️ Limitations

🐛 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

  1. Always Handle Errors: Monitor the error signal
  2. Clear on Destroy: Call clear() in ngOnDestroy
  3. Use Signals: Leverage reactive signals for state
  4. Device Testing: Test on all device sizes
  5. Theme Testing: Verify all theme variants
  6. Performance: Disable hot reload in production

🚀 Future Enhancements

💡 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:


Last Updated: 2025-01-10 Version: 1.0.0 Status: ✅ Production Ready