@breadstone/ziegel-platform-presentation ​
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> {
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
Related Packages ​
- @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> {
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<void> {
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>
);
};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<{ destroy(): void }> = [];
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:
- Install the platform presentation package
- Update imports to use platform-specific features
- 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';Related Packages ​
- @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 ​
- Commands not executing: Check canExecute conditions and error handling
- Type converters not working: Ensure converters are properly registered
- 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.