Files
ui-essentials/projects/demo-ui-essentials/src/app/demos/file-upload-demo/file-upload-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

399 lines
13 KiB
TypeScript

import { Component } from '@angular/core';
import { CommonModule } from '@angular/common';
import { FormControl, FormGroup, ReactiveFormsModule, Validators } from '@angular/forms';
import { FileUploadComponent, UploadedFile } from '../../../../../ui-essentials/src/lib/components/forms/file-upload/file-upload.component';
@Component({
selector: 'ui-file-upload-demo',
standalone: true,
imports: [CommonModule, ReactiveFormsModule, FileUploadComponent],
template: `
<div class="demo-container">
<h2>File Upload Demo</h2>
<!-- Size Variants -->
<section class="demo-section">
<h3>Sizes</h3>
<div class="demo-grid">
@for (size of sizes; track size) {
<div class="demo-item">
<h4>{{ size.toUpperCase() }} Size</h4>
<p>File upload with {{ size }} sizing.</p>
<ui-file-upload
[size]="size"
label="Upload Files ({{ size }})"
[multiple]="true"
helperText="Select one or more files to upload"
(filesSelected)="onFilesSelected('size-' + size, $event)"
>
</ui-file-upload>
</div>
}
</div>
</section>
<!-- Variant Styles -->
<section class="demo-section">
<h3>Variants</h3>
<div class="demo-grid">
@for (variant of variants; track variant) {
<div class="demo-item">
<h4>{{ variant | titlecase }} Variant</h4>
<p>File upload with {{ variant }} styling.</p>
<ui-file-upload
[variant]="variant"
label="Upload Files ({{ variant }})"
[multiple]="true"
helperText="Drag & drop or browse to select files"
(filesSelected)="onFilesSelected('variant-' + variant, $event)"
>
</ui-file-upload>
</div>
}
</div>
</section>
<!-- File Type Restrictions -->
<section class="demo-section">
<h3>File Type Restrictions</h3>
<div class="demo-grid">
<div class="demo-item">
<h4>Images Only</h4>
<p>Accepts only image files (JPEG, PNG, GIF, WebP).</p>
<ui-file-upload
label="Upload Images"
[acceptedTypes]="['image/jpeg', 'image/png', 'image/gif', 'image/webp']"
accept="image/*"
[multiple]="true"
helperText="Only image files are accepted"
(filesSelected)="onFilesSelected('images', $event)"
>
</ui-file-upload>
</div>
<div class="demo-item">
<h4>Documents Only</h4>
<p>Accepts PDF, Word, and Excel documents.</p>
<ui-file-upload
label="Upload Documents"
[acceptedTypes]="['.pdf', '.doc', '.docx', '.xls', '.xlsx']"
accept=".pdf,.doc,.docx,.xls,.xlsx"
[multiple]="true"
helperText="PDF, Word, and Excel files only"
(filesSelected)="onFilesSelected('documents', $event)"
>
</ui-file-upload>
</div>
</div>
</section>
<!-- Size Limits -->
<section class="demo-section">
<h3>Size & File Limits</h3>
<div class="demo-grid">
<div class="demo-item">
<h4>Size Limit (5MB)</h4>
<p>Maximum file size of 5MB per file.</p>
<ui-file-upload
label="Upload Files (5MB limit)"
[maxFileSize]="5242880"
[multiple]="true"
helperText="Max file size: 5MB"
(filesSelected)="onFilesSelected('size-limit', $event)"
>
</ui-file-upload>
</div>
<div class="demo-item">
<h4>File Count Limit</h4>
<p>Maximum of 3 files can be selected.</p>
<ui-file-upload
label="Upload Files (3 max)"
[maxFiles]="3"
[multiple]="true"
helperText="Maximum 3 files allowed"
(filesSelected)="onFilesSelected('file-limit', $event)"
>
</ui-file-upload>
</div>
<div class="demo-item">
<h4>Single File</h4>
<p>Only one file can be selected.</p>
<ui-file-upload
label="Upload Single File"
[multiple]="false"
helperText="Select a single file to upload"
(filesSelected)="onFilesSelected('single-file', $event)"
>
</ui-file-upload>
</div>
</div>
</section>
<!-- States -->
<section class="demo-section">
<h3>States</h3>
<div class="demo-grid">
<div class="demo-item">
<h4>Disabled State</h4>
<p>File upload in disabled state.</p>
<ui-file-upload
label="Disabled Upload"
[disabled]="true"
helperText="This upload is disabled"
(filesSelected)="onFilesSelected('disabled', $event)"
>
</ui-file-upload>
</div>
<div class="demo-item">
<h4>Error State</h4>
<p>File upload showing error state.</p>
<ui-file-upload
label="Upload with Error"
state="error"
errorMessage="Please select valid files"
[multiple]="true"
(filesSelected)="onFilesSelected('error', $event)"
>
</ui-file-upload>
</div>
<div class="demo-item">
<h4>Success State</h4>
<p>File upload showing success state.</p>
<ui-file-upload
label="Successful Upload"
state="success"
helperText="Files uploaded successfully!"
[multiple]="true"
(filesSelected)="onFilesSelected('success', $event)"
>
</ui-file-upload>
</div>
</div>
</section>
<!-- Reactive Form Integration -->
<section class="demo-section">
<h3>Reactive Form Integration</h3>
<div class="demo-item">
<h4>Form with Validation</h4>
<p>File upload integrated with Angular reactive forms and validation.</p>
<form [formGroup]="uploadForm" (ngSubmit)="onSubmit()">
<ui-file-upload
label="Required File Upload"
formControlName="files"
[multiple]="true"
[required]="true"
[acceptedTypes]="['.pdf', '.doc', '.docx', 'image/*']"
[maxFileSize]="10485760"
[maxFiles]="5"
helperText="Required field - select 1-5 files (PDF, Word, or images, max 10MB each)"
[state]="getFormFieldState('files')"
[errorMessage]="getFormFieldError('files')"
(filesSelected)="onFormFilesSelected($event)"
>
</ui-file-upload>
<div class="demo-actions">
<button
type="submit"
class="demo-button"
[disabled]="uploadForm.invalid"
>
Submit Form
</button>
<button
type="button"
class="demo-button demo-button--secondary"
(click)="resetForm()"
>
Reset
</button>
<div class="demo-info">
Form Status: {{ uploadForm.status }} |
Form Valid: {{ uploadForm.valid }} |
Files Count: {{ uploadForm.get('files')?.value?.length || 0 }}
</div>
</div>
</form>
@if (submittedFiles.length > 0) {
<div class="file-list-demo">
<h5>Submitted Files:</h5>
@for (file of submittedFiles; track file.id) {
<div class="file-item">
<div>
<div class="file-info">{{ file.name }}</div>
<div class="file-size">{{ formatFileSize(file.size) }}</div>
</div>
</div>
}
</div>
}
</div>
</section>
<!-- Event Handling -->
<section class="demo-section">
<h3>Event Handling</h3>
<div class="demo-item">
<h4>Event Monitoring</h4>
<p>Monitor file upload events in real-time.</p>
<ui-file-upload
label="Event Demo Upload"
[multiple]="true"
[maxFiles]="3"
helperText="Add/remove files to see events below"
(filesSelected)="onEventFilesSelected($event)"
(fileAdded)="onFileAdded($event)"
(fileRemoved)="onFileRemoved($event)"
>
</ui-file-upload>
<div class="file-list-demo">
<h5>Recent Events:</h5>
@if (recentEvents.length === 0) {
<p class="demo-info">No events yet. Add or remove files to see events.</p>
} @else {
@for (event of recentEvents.slice(-5).reverse(); track $index) {
<div class="file-item">
<div>
<div class="file-info">{{ event.type }}: {{ event.fileName }}</div>
<div class="file-size">{{ event.timestamp | date:'medium' }}</div>
</div>
</div>
}
}
</div>
</div>
</section>
<!-- Code Example -->
<section class="demo-section">
<h3>Usage Example</h3>
<div class="code-demo">
<pre><code>{{ codeExample }}</code></pre>
</div>
</section>
</div>
`,
styleUrl: './file-upload-demo.component.scss'
})
export class FileUploadDemoComponent {
sizes = ['sm', 'md', 'lg'] as const;
variants = ['outlined', 'filled', 'underlined'] as const;
uploadForm = new FormGroup({
files: new FormControl<UploadedFile[]>([], [Validators.required])
});
submittedFiles: UploadedFile[] = [];
recentEvents: Array<{type: string, fileName: string, timestamp: Date}> = [];
readonly codeExample = `import { FileUploadComponent, UploadedFile } from '../../../../../ui-essentials/src/lib/components/forms/file-upload/file-upload.component';
// Basic usage
<ui-file-upload
label="Upload Files"
[multiple]="true"
[acceptedTypes]="['image/*', '.pdf']"
[maxFileSize]="5242880"
[maxFiles]="5"
helperText="Select up to 5 files (images or PDF, max 5MB each)"
(filesSelected)="onFilesSelected($event)"
>
</ui-file-upload>
// With reactive forms
<ui-file-upload
formControlName="files"
[required]="true"
[state]="getFieldState('files')"
[errorMessage]="getFieldError('files')"
>
</ui-file-upload>
// Event handling
onFilesSelected(files: UploadedFile[]): void {
console.log('Selected files:', files);
files.forEach(file => {
console.log(file.name, file.size, file.type);
});
}`;
onFilesSelected(context: string, files: UploadedFile[]): void {
console.log(`Files selected in ${context}:`, files);
}
onFormFilesSelected(files: UploadedFile[]): void {
this.uploadForm.patchValue({ files });
this.uploadForm.get('files')?.markAsTouched();
}
onEventFilesSelected(files: UploadedFile[]): void {
this.addEvent('filesSelected', `${files.length} files total`);
}
onFileAdded(file: UploadedFile): void {
this.addEvent('fileAdded', file.name);
}
onFileRemoved(file: UploadedFile): void {
this.addEvent('fileRemoved', file.name);
}
private addEvent(type: string, fileName: string): void {
this.recentEvents.push({
type,
fileName,
timestamp: new Date()
});
}
onSubmit(): void {
if (this.uploadForm.valid) {
this.submittedFiles = this.uploadForm.get('files')?.value || [];
console.log('Form submitted with files:', this.submittedFiles);
}
}
resetForm(): void {
this.uploadForm.reset();
this.uploadForm.get('files')?.setValue([]);
this.submittedFiles = [];
}
getFormFieldState(fieldName: string): 'default' | 'error' | 'success' {
const control = this.uploadForm.get(fieldName);
if (control?.invalid && control?.touched) {
return 'error';
}
if (control?.valid && control?.value?.length > 0) {
return 'success';
}
return 'default';
}
getFormFieldError(fieldName: string): string {
const control = this.uploadForm.get(fieldName);
if (control?.invalid && control?.touched) {
if (control.errors?.['required']) {
return 'Please select at least one file';
}
}
return '';
}
formatFileSize(bytes: number): string {
if (bytes === 0) return '0 Bytes';
const k = 1024;
const sizes = ['Bytes', 'KB', 'MB', 'GB'];
const i = Math.floor(Math.log(bytes) / Math.log(k));
return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i];
}
}