Skip to content

@breadstone/ziegel-platform-presentation ​

MIT LicenseTypeScriptnpm

Platform-level presentation services for the ziegel framework. Provides view models, presentation patterns, and UI coordination services for enterprise applications.

Platform Presentation: Enterprise presentation patterns with view models, coordinators, and platform-level UI services.

🚀 Overview ​

@breadstone/ziegel-platform-presentation provides:

  • View Models: MVVM pattern implementation with data binding
  • Presentation Services: Platform services for UI coordination
  • View Coordinators: Navigation and view lifecycle management
  • Data Binding: Two-way data binding for reactive UIs
  • Command Patterns: UI command handling and routing
  • Validation Integration: Form validation and error handling

📦 Installation ​

bash
npm install @breadstone/ziegel-platform-presentation
# or
yarn add @breadstone/ziegel-platform-presentation

🧩 Features & Usage Examples ​

View Models ​

typescript
import { ViewModelBase, bindable } from '@breadstone/ziegel-platform-presentation';

class UserViewModel extends ViewModelBase {
  @bindable name: string = '';
  @bindable email: string = '';

  async save() {
    // Save logic
  }
}

Presentation Coordinators ​

typescript
import { PresentationCoordinator } from '@breadstone/ziegel-platform-presentation';

class UserCoordinator extends PresentationCoordinator {
  async showUserDetails(userId: string) {
    const viewModel = new UserViewModel();
    await this.presentView('user-details', viewModel);
  }
}

Command Handling ​

typescript
import { CommandHandler, ICommand } from '@breadstone/ziegel-platform-presentation';

class SaveUserCommand implements ICommand {
  constructor(public user: User) {}
}

class SaveUserHandler extends CommandHandler<SaveUserCommand&gt; {
  async handle(command: SaveUserCommand) {
    // Handle save operation
  }
}

📚 Package import points ​

typescript
import {
    // View Models
    ViewModelBase,
    bindable,

    // Coordinators
    PresentationCoordinator,

    // Commands
    CommandHandler,
    ICommand,

    // Services
    PresentationService
} from '@breadstone/ziegel-platform-presentation';

📚 API Documentation ​

For detailed API documentation, visit: API Docs

  • @breadstone/ziegel-platform: Core platform services
  • @breadstone/ziegel-presentation: Base presentation utilities
  • @breadstone/ziegel-core: Foundation utilities

License ​

MIT

Issues ​

Please report bugs and feature requests in the Issue Tracker


Part of the ziegel Enterprise TypeScript Framework const size = TypeConverters.convert('size', '100x200');


### Enhanced UI Services

```typescript
import {
  ClipboardService,
  AnchorScrollService,
  BusyService,
  ScrollRevealService,
  ScrollSpyService,
  TextToSpeechService
} from '@breadstone/ziegel-platform-presentation';

// Clipboard operations
const clipboardService = new ClipboardService();
await clipboardService.writeText('Hello, World!');
const clipboardText = await clipboardService.readText();

// Smooth scrolling
const anchorScrollService = new AnchorScrollService({
  duration: 1000,
  easing: 'easeInOutCubic',
  offset: 50
});
anchorScrollService.scrollToElement('#target-element');

// Busy state management
const busyService = new BusyService();
busyService.setBusy('Loading data...');
// Later...
busyService.clearBusy();

// Text-to-speech
const ttsService = new TextToSpeechService({
  rate: 1.0,
  pitch: 1.0,
  volume: 1.0,
  lang: 'en-US'
});
await ttsService.speak('Hello, this is a text-to-speech example');

Scroll Reveal and Spy ​

typescript
// Scroll reveal animations
const scrollRevealService = new ScrollRevealService({
  threshold: 0.15,
  distance: '50px',
  duration: 600,
  delay: 100,
  reset: false
});

scrollRevealService.reveal('.animate-on-scroll');

// Scroll spy for navigation
const scrollSpyService = new ScrollSpyService({
  offset: 100,
  activeClass: 'active',
  smooth: true
});

scrollSpyService.init(['#section1', '#section2', '#section3']);

Command Descriptors ​

typescript
import {
  CommandDescriptor,
  MenuCommandDescriptor,
  IHotKey
} from '@breadstone/ziegel-platform-presentation';

// Create command descriptor
const commandDescriptor = new CommandDescriptor({
  id: 'save-file',
  label: 'Save File',
  icon: 'save-icon',
  tooltip: 'Save the current file',
  command: saveCommand,
  hotKey: { key: 'S', ctrl: true } as IHotKey
});

// Menu command descriptor
const menuCommandDescriptor = new MenuCommandDescriptor({
  id: 'file-menu',
  label: 'File',
  children: [
    {
      id: 'new-file',
      label: 'New File',
      command: newFileCommand,
      hotKey: { key: 'N', ctrl: true }
    },
    {
      id: 'open-file',
      label: 'Open File',
      command: openFileCommand,
      hotKey: { key: 'O', ctrl: true }
    }
  ]
});

Media Query Management ​

typescript
import {
  MediaQueryService,
  IMediaQueryRule
} from '@breadstone/ziegel-platform-presentation';

const mediaQueryService = new MediaQueryService();

// Define media query rules
const rules: IMediaQueryRule[] = [
  {
    name: 'mobile',
    query: '(max-width: 768px)',
    matches: false
  },
  {
    name: 'tablet',
    query: '(min-width: 769px) and (max-width: 1024px)',
    matches: false
  },
  {
    name: 'desktop',
    query: '(min-width: 1025px)',
    matches: false
  }
];

mediaQueryService.register(rules);

// Listen for changes
mediaQueryService.changes$.subscribe(activeRules => {
  console.log('Active media queries:', activeRules);
});

Advanced Features ​

Reactive Command Patterns ​

typescript
import { ReactiveCommand } from '@breadstone/ziegel-platform-presentation';
import { of, timer, EMPTY } from 'rxjs';
import { switchMap, catchError } from 'rxjs/operators';

// Async command with loading states
const asyncCommand = new ReactiveCommand(
  (param: string) => {
    return timer(1000).pipe(
      switchMap(() => this.apiService.processData(param)),
      catchError(error => {
        console.error('Command failed:', error);
        return EMPTY;
      })
    );
  },
  {
    canExecute: this.isDataValid$,
    outputScheduler: asyncScheduler
  }
);

// Subscribe to execution states
asyncCommand.isExecuting$.subscribe(isExecuting => {
  console.log('Command executing:', isExecuting);
});

asyncCommand.results$.subscribe(result => {
  console.log('Command result:', result);
});

Custom Type Converters ​

typescript
import { TypeConverterBase } from '@breadstone/ziegel-platform-presentation';

class ColorTypeConverter extends TypeConverterBase<string, string&gt; {
  public convert(value: string): string {
    // Convert hex to RGB
    if (value.startsWith('#')) {
      const hex = value.slice(1);
      const r = parseInt(hex.slice(0, 2), 16);
      const g = parseInt(hex.slice(2, 4), 16);
      const b = parseInt(hex.slice(4, 6), 16);
      return `rgb(${r}, ${g}, ${b})`;
    }
    return value;
  }

  public convertBack(value: string): string {
    // Convert RGB to hex
    const match = value.match(/rgb\((\d+),\s*(\d+),\s*(\d+)\)/);
    if (match) {
      const [, r, g, b] = match;
      return `#${[r, g, b].map(x => parseInt(x).toString(16).padStart(2, '0')).join('')}`;
    }
    return value;
  }
}

// Register custom converter
TypeConverters.register('color', new ColorTypeConverter());

Service Composition ​

typescript
class PresentationServiceComposer {
  private readonly clipboardService = new ClipboardService();
  private readonly busyService = new BusyService();
  private readonly ttsService = new TextToSpeechService();

  public async performComplexOperation(data: any): Promise&lt;void&gt; {
    try {
      this.busyService.setBusy('Processing data...');

      // Process data
      const result = await this.processData(data);

      // Copy result to clipboard
      await this.clipboardService.writeText(JSON.stringify(result));

      // Announce completion
      await this.ttsService.speak('Operation completed successfully');

    } catch (error) {
      await this.ttsService.speak('Operation failed');
      throw error;
    } finally {
      this.busyService.clearBusy();
    }
  }
}

Configuration ​

Service Configuration ​

typescript
// Configure services with options
const services = {
  anchorScroll: new AnchorScrollService({
    duration: 800,
    easing: 'easeInOutQuart',
    offset: 60,
    updateURL: true
  }),

  scrollReveal: new ScrollRevealService({
    threshold: 0.1,
    distance: '30px',
    duration: 800,
    delay: 200,
    reset: true,
    mobile: true
  }),

  textToSpeech: new TextToSpeechService({
    rate: 0.9,
    pitch: 1.1,
    volume: 0.8,
    lang: 'en-US',
    voiceURI: 'Google US English'
  })
};

HTTP Interceptor Configuration ​

typescript
// Configure HTTP interceptors
const httpConfig = {
  onlineOffline: {
    retryAttempts: 3,
    retryDelay: 1000,
    showOfflineMessage: true
  },

  responseEvent: {
    enableGlobalErrorHandling: true,
    enableSuccessNotifications: false,
    enableProgressTracking: true
  }
};

Integration Examples ​

React Integration ​

typescript
import React, { useEffect, useState } from 'react';
import { BusyService, ScrollRevealService } from '@breadstone/ziegel-platform-presentation';

export const PresentationProvider: React.FC<{ children: React.ReactNode }> = ({ children }) => {
  const [busyService] = useState(() => new BusyService());
  const [scrollRevealService] = useState(() => new ScrollRevealService());

  useEffect(() => {
    scrollRevealService.reveal('.reveal-element');

    return () => {
      scrollRevealService.cleanup();
    };
  }, [scrollRevealService]);

  return (
    <PresentationContext.Provider value={{ busyService, scrollRevealService }}>
      {children}
    </PresentationContext.Provider&gt;
  );
};

Angular Integration ​

typescript
import { Injectable, NgModule } from '@angular/core';
import { HTTP_INTERCEPTORS } from '@angular/common/http';
import { OnlineOfflineHttpInterceptor } from '@breadstone/ziegel-platform-presentation';

@Injectable()
export class PresentationInterceptor extends OnlineOfflineHttpInterceptor {}

@NgModule({
  providers: [
    {
      provide: HTTP_INTERCEPTORS,
      useClass: PresentationInterceptor,
      multi: true
    }
  ]
})
export class PresentationModule {}

Best Practices ​

1. Command Organization ​

typescript
// Group related commands
export class DocumentCommands {
  public readonly save = new ReactiveCommand(/* ... */);
  public readonly saveAs = new ReactiveCommand(/* ... */);
  public readonly export = new ReactiveCommand(/* ... */);
  public readonly print = new ReactiveCommand(/* ... */);
}

2. Service Lifecycle Management ​

typescript
class ServiceManager {
  private services: Array&lt;{ destroy(): void }&gt; = [];

  public register<T extends { destroy(): void }>(service: T): T {
    this.services.push(service);
    return service;
  }

  public destroy(): void {
    this.services.forEach(service => service.destroy());
    this.services.length = 0;
  }
}

3. Error Handling ​

typescript
// Centralized error handling for UI operations
class PresentationErrorHandler {
  public handleError(error: any, context: string): void {
    console.error(`Error in ${context}:`, error);

    // Show user-friendly message
    this.notificationService.showError('An error occurred. Please try again.');

    // Track error for analytics
    this.analyticsService.trackError(error, context);
  }
}

Migration Guide ​

From Base Presentation Package ​

This package extends the base @breadstone/ziegel-presentation package. When migrating:

  1. Install the platform presentation package
  2. Update imports to use platform-specific features
  3. Configure enhanced services as needed
typescript
// Before (base package)
import { ClipboardService } from '@breadstone/ziegel-presentation';

// After (platform package)
import { ClipboardService } from '@breadstone/ziegel-platform-presentation';
  • @breadstone/ziegel-presentation: Base presentation layer
  • @breadstone/ziegel-platform: Core platform services
  • @breadstone/ziegel-platform-navigation: Navigation management
  • @breadstone/ziegel-platform-messaging: Messaging system

Troubleshooting ​

Common Issues ​

  1. Commands not executing: Check canExecute conditions and error handling
  2. Type converters not working: Ensure converters are properly registered
  3. Services not disposing: Implement proper cleanup in component lifecycle

Debug Configuration ​

typescript
// Enable debug mode for services
const config = {
  debug: true,
  logLevel: 'verbose',
  enablePerformanceMetrics: true
};

API Reference ​

For detailed API documentation, see the auto-generated API reference.