Files
ui-essentials/projects/demo-ui-essentials/src/app/demos/image-container-demo/image-container-demo.component.ts
skyai_dev 6f0ab0cf5f Fix SCSS semantic token variable errors across components
- Replace incorrect semantic token names with correct ones:
  • $semantic-border-width-thin → $semantic-border-width-1
  • $semantic-color-border-default → $semantic-color-border-primary
  • $semantic-spacing-content-* → $semantic-spacing-component-*
  • $semantic-typography-body-* → $semantic-typography-font-size-*
  • $semantic-typography-caption-* → $semantic-typography-font-size-*
  • $semantic-motion-easing-standard → $semantic-easing-standard
  • $semantic-color-surface-tertiary → $semantic-color-surface-secondary
  • Various hover color tokens → base color tokens

- Fix typography map usage errors:
  • Replace heading map tokens with individual size tokens
  • $semantic-typography-heading-h* → $semantic-typography-heading-h*-size

- Update affected components:
  • tooltip, divider, progress-circle, range-slider components
  • Related demo components and SCSS files

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-09-03 07:50:34 +10:00

311 lines
11 KiB
TypeScript

import { Component } from '@angular/core';
import { CommonModule } from '@angular/common';
import { ImageContainerComponent, ImageContainerSize, ImageContainerAspectRatio, ImageContainerObjectFit, ImageContainerShape } from '../../../../../ui-essentials/src/lib/components/data-display/image-container/image-container.component';
import { BadgeComponent } from '../../../../../ui-essentials/src/lib/components/data-display/badge/badge.component';
import { FontAwesomeModule } from '@fortawesome/angular-fontawesome';
import { faRefresh, faHeart, faPlay } from '@fortawesome/free-solid-svg-icons';
@Component({
selector: 'ui-image-container-demo',
standalone: true,
imports: [CommonModule, ImageContainerComponent, BadgeComponent, FontAwesomeModule],
template: `
<div class="demo-container">
<h2>Image Container Demo</h2>
<p>A flexible image container with lazy loading, aspect ratios, and various display options.</p>
<!-- Size Variants -->
<section class="demo-section">
<h3>Sizes</h3>
<div class="demo-row">
@for (size of sizes; track size) {
<div class="demo-item">
<ui-image-container
[size]="size"
[src]="sampleImages.landscape"
[alt]="'Sample image - ' + size + ' size'">
</ui-image-container>
<span class="demo-label">{{ size }}</span>
</div>
}
</div>
</section>
<!-- Aspect Ratios -->
<section class="demo-section">
<h3>Aspect Ratios</h3>
<div class="demo-grid">
@for (ratio of aspectRatios; track ratio) {
<div class="demo-item">
<ui-image-container
size="md"
[aspectRatio]="ratio"
[src]="sampleImages.landscape"
[alt]="'Sample image - ' + ratio + ' aspect ratio'">
</ui-image-container>
<span class="demo-label">{{ ratio }}</span>
</div>
}
</div>
</section>
<!-- Object Fit Options -->
<section class="demo-section">
<h3>Object Fit</h3>
<div class="demo-row">
@for (fit of objectFits; track fit) {
<div class="demo-item">
<ui-image-container
size="md"
aspectRatio="1/1"
[objectFit]="fit"
[src]="sampleImages.landscape"
[alt]="'Sample image with ' + fit + ' object fit'">
</ui-image-container>
<span class="demo-label">{{ fit }}</span>
</div>
}
</div>
</section>
<!-- Shape Variants -->
<section class="demo-section">
<h3>Shapes</h3>
<div class="demo-row">
@for (shape of shapes; track shape) {
<div class="demo-item">
<ui-image-container
size="md"
aspectRatio="1/1"
[shape]="shape"
[src]="sampleImages.portrait"
[alt]="'Sample image with ' + shape + ' shape'">
</ui-image-container>
<span class="demo-label">{{ shape }}</span>
</div>
}
</div>
</section>
<!-- Loading States -->
<section class="demo-section">
<h3>Loading States</h3>
<div class="demo-row">
<div class="demo-item">
<ui-image-container
size="md"
[loading]="true"
src="placeholder"
alt="Loading image">
</ui-image-container>
<span class="demo-label">Loading</span>
</div>
<div class="demo-item">
<ui-image-container
size="md"
src="invalid-url.jpg"
alt="Failed to load image">
<div slot="error">
<fa-icon [icon]="faRefresh" size="lg"></fa-icon>
<span>Custom Error</span>
<button class="retry-btn" (click)="retryImage($event)">Retry</button>
</div>
</ui-image-container>
<span class="demo-label">Error State</span>
</div>
<div class="demo-item">
<ui-image-container
size="md"
[src]="sampleImages.landscape"
[lazy]="false"
alt="Eager loaded image">
</ui-image-container>
<span class="demo-label">Eager Load</span>
</div>
</div>
</section>
<!-- Interactive Features -->
<section class="demo-section">
<h3>Interactive Features</h3>
<div class="demo-row">
<div class="demo-item">
<ui-image-container
size="lg"
aspectRatio="16/9"
[src]="sampleImages.landscape"
[overlay]="true"
alt="Image with overlay"
(imageClick)="handleImageClick('overlay')">
<div slot="overlay">
<fa-icon [icon]="faPlay" size="2x"></fa-icon>
<span>Play Video</span>
</div>
</ui-image-container>
<span class="demo-label">With Overlay</span>
</div>
<div class="demo-item">
<ui-image-container
size="lg"
aspectRatio="4/3"
[src]="sampleImages.landscape"
caption="Beautiful landscape scene"
alt="Image with caption"
(imageClick)="handleImageClick('caption')">
</ui-image-container>
<span class="demo-label">With Caption</span>
</div>
</div>
</section>
<!-- Advanced Examples -->
<section class="demo-section">
<h3>Advanced Examples</h3>
<div class="demo-row">
<div class="demo-item">
<ui-image-container
size="lg"
aspectRatio="1/1"
shape="circle"
[src]="sampleImages.portrait"
[overlay]="true"
alt="Profile picture with status"
(imageClick)="handleImageClick('profile')">
<div slot="overlay">
<fa-icon [icon]="faHeart" style="color: red;"></fa-icon>
</div>
</ui-image-container>
<span class="demo-label">Profile Avatar</span>
</div>
<div class="demo-item">
<ui-image-container
size="xl"
aspectRatio="16/9"
[src]="sampleImages.landscape"
caption="Hero image with custom styling"
alt="Hero banner image"
class="hero-image">
<div slot="caption">
<h4>Custom Caption Content</h4>
<p>With additional styled elements</p>
<ui-badge variant="primary" size="xs">Featured</ui-badge>
</div>
</ui-image-container>
<span class="demo-label">Hero Banner</span>
</div>
</div>
</section>
<!-- Responsive Gallery -->
<section class="demo-section">
<h3>Responsive Gallery</h3>
<div class="demo-gallery">
@for (image of galleryImages; track image.id; let i = $index) {
<ui-image-container
size="md"
[aspectRatio]="i % 3 === 0 ? '16/9' : '1/1'"
[src]="image.url"
[alt]="image.alt"
[overlay]="true"
(imageClick)="handleGalleryClick(image, i)"
(imageLoaded)="handleImageLoad(image.id)"
(imageError)="handleImageError(image.id)">
<div slot="overlay">
<span>{{ image.title }}</span>
</div>
</ui-image-container>
}
</div>
</section>
<!-- Event Log -->
@if (eventLog.length > 0) {
<section class="demo-section">
<h3>Event Log</h3>
<div class="event-log">
@for (event of eventLog.slice(-5); track event.id) {
<div class="event-item">
<span class="event-time">{{ event.time | date:'HH:mm:ss' }}</span>
<span class="event-type">{{ event.type }}</span>
<span class="event-message">{{ event.message }}</span>
</div>
}
</div>
</section>
}
</div>
`,
styleUrl: './image-container-demo.component.scss'
})
export class ImageContainerDemoComponent {
// Icons
faRefresh = faRefresh;
faHeart = faHeart;
faPlay = faPlay;
// Demo data
sizes: ImageContainerSize[] = ['sm', 'md', 'lg', 'xl'];
aspectRatios: ImageContainerAspectRatio[] = ['1/1', '4/3', '16/9', '3/2', '2/1', '3/4', '9/16'];
objectFits: ImageContainerObjectFit[] = ['contain', 'cover', 'fill', 'scale-down'];
shapes: ImageContainerShape[] = ['square', 'rounded', 'circle'];
// Sample images (using placeholder service)
sampleImages = {
landscape: 'https://picsum.photos/800/600?random=1',
portrait: 'https://picsum.photos/600/800?random=2',
square: 'https://picsum.photos/600/600?random=3'
};
galleryImages = [
{ id: 1, url: 'https://picsum.photos/400/400?random=10', title: 'Nature', alt: 'Beautiful nature scene' },
{ id: 2, url: 'https://picsum.photos/400/300?random=11', title: 'Architecture', alt: 'Modern building' },
{ id: 3, url: 'https://picsum.photos/400/500?random=12', title: 'Portrait', alt: 'Person portrait' },
{ id: 4, url: 'https://picsum.photos/400/400?random=13', title: 'Urban', alt: 'City landscape' },
{ id: 5, url: 'https://picsum.photos/400/300?random=14', title: 'Technology', alt: 'Tech equipment' },
{ id: 6, url: 'https://picsum.photos/400/400?random=15', title: 'Abstract', alt: 'Abstract art' }
];
// Event tracking
eventLog: Array<{id: number, type: string, message: string, time: Date}> = [];
private eventId = 1;
handleImageClick(context: string): void {
this.logEvent('click', `Image clicked in ${context} context`);
}
handleGalleryClick(image: any, index: number): void {
this.logEvent('gallery-click', `Gallery image "${image.title}" clicked (index ${index})`);
}
handleImageLoad(imageId: number): void {
this.logEvent('load', `Image ${imageId} loaded successfully`);
}
handleImageError(imageId: number): void {
this.logEvent('error', `Image ${imageId} failed to load`);
}
retryImage(event: Event): void {
event.stopPropagation();
this.logEvent('retry', 'Retry button clicked for failed image');
// In a real implementation, this would retry loading the image
}
private logEvent(type: string, message: string): void {
this.eventLog.push({
id: this.eventId++,
type,
message,
time: new Date()
});
// Keep only last 20 events
if (this.eventLog.length > 20) {
this.eventLog.splice(0, this.eventLog.length - 20);
}
}
}