Add comprehensive component library and demo application

Added extensive component library with feedback components (empty state, loading spinner, skeleton loader), enhanced form components (autocomplete, date picker, file upload, form field, time picker), navigation components (pagination), and overlay components (backdrop, drawer, modal, overlay container). Updated demo application with comprehensive showcase components and enhanced styling throughout the project. Excluded font files from repository to reduce size.

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

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
skyai_dev
2025-09-03 05:38:09 +10:00
parent c803831f60
commit 5983722793
246 changed files with 52845 additions and 25 deletions

View File

@@ -0,0 +1,584 @@
import { Component, ChangeDetectionStrategy, signal } from '@angular/core';
import { CommonModule } from '@angular/common';
import { FormsModule } from '@angular/forms';
import { ProgressBarComponent } from '../../../../../ui-essentials/src/lib/components/data-display/progress';
@Component({
selector: 'ui-progress-demo',
standalone: true,
imports: [
CommonModule,
FormsModule,
ProgressBarComponent
],
changeDetection: ChangeDetectionStrategy.OnPush,
template: `
<div style="padding: 2rem;">
<h2>Progress Bar Component Showcase</h2>
<!-- Basic Progress Bars -->
<section style="margin-bottom: 3rem;">
<h3>Basic Progress Bars</h3>
<div style="display: flex; flex-direction: column; gap: 2rem;">
<ui-progress-bar
label="Small Progress"
size="sm"
[progress]="25"
helperText="25% complete">
</ui-progress-bar>
<ui-progress-bar
label="Medium Progress"
size="md"
[progress]="50"
helperText="50% complete">
</ui-progress-bar>
<ui-progress-bar
label="Large Progress"
size="lg"
[progress]="75"
helperText="75% complete">
</ui-progress-bar>
</div>
</section>
<!-- Progress Bar Variants -->
<section style="margin-bottom: 3rem;">
<h3>Color Variants</h3>
<div style="display: flex; flex-direction: column; gap: 2rem;">
<ui-progress-bar
label="Primary Progress"
variant="primary"
[progress]="60"
helperText="Default brand color">
</ui-progress-bar>
<ui-progress-bar
label="Secondary Progress"
variant="secondary"
[progress]="45"
helperText="Secondary color variant">
</ui-progress-bar>
<ui-progress-bar
label="Success Progress"
variant="success"
[progress]="80"
helperText="Indicates successful completion">
</ui-progress-bar>
<ui-progress-bar
label="Warning Progress"
variant="warning"
[progress]="30"
helperText="Indicates caution or attention needed">
</ui-progress-bar>
<ui-progress-bar
label="Danger Progress"
variant="danger"
[progress]="15"
helperText="Indicates error or critical state">
</ui-progress-bar>
</div>
</section>
<!-- Progress Bar Types -->
<section style="margin-bottom: 3rem;">
<h3>Progress Bar Types</h3>
<div style="display: flex; flex-direction: column; gap: 2rem;">
<ui-progress-bar
label="Determinate Progress"
progressType="determinate"
[progress]="determinateProgress()"
helperText="Shows exact progress value">
</ui-progress-bar>
<ui-progress-bar
label="Indeterminate Progress"
progressType="indeterminate"
variant="primary"
helperText="Shows ongoing activity without specific progress">
</ui-progress-bar>
<ui-progress-bar
label="Buffer Progress"
progressType="buffer"
[progress]="bufferProgress()"
[buffer]="bufferValue()"
variant="secondary"
helperText="Shows buffered content loading">
</ui-progress-bar>
</div>
</section>
<!-- Striped and Animated -->
<section style="margin-bottom: 3rem;">
<h3>Striped and Animated Progress Bars</h3>
<div style="display: flex; flex-direction: column; gap: 2rem;">
<ui-progress-bar
label="Striped Progress"
[progress]="65"
[striped]="true"
helperText="With striped pattern">
</ui-progress-bar>
<ui-progress-bar
label="Animated Striped Progress"
[progress]="55"
[striped]="true"
[animated]="true"
variant="success"
helperText="With animated stripes">
</ui-progress-bar>
<ui-progress-bar
label="Animated Indeterminate"
progressType="indeterminate"
[animated]="true"
variant="primary"
helperText="Smooth indeterminate animation">
</ui-progress-bar>
</div>
</section>
<!-- States -->
<section style="margin-bottom: 3rem;">
<h3>Progress Bar States</h3>
<div style="display: flex; flex-direction: column; gap: 2rem;">
<ui-progress-bar
label="Normal State"
[progress]="70"
helperText="Default active state">
</ui-progress-bar>
<ui-progress-bar
label="Disabled State"
[progress]="40"
state="disabled"
helperText="Disabled progress bar">
</ui-progress-bar>
</div>
</section>
<!-- Size Comparison -->
<section style="margin-bottom: 3rem;">
<h3>Size and Variant Combinations</h3>
<div style="display: grid; grid-template-columns: 1fr 1fr; gap: 2rem; max-width: 1200px;">
<!-- Small sizes -->
<div>
<h4>Small Size Variants</h4>
<div style="display: flex; flex-direction: column; gap: 1rem;">
<ui-progress-bar size="sm" variant="primary" [progress]="25" label="Primary Small"></ui-progress-bar>
<ui-progress-bar size="sm" variant="success" [progress]="50" label="Success Small"></ui-progress-bar>
<ui-progress-bar size="sm" variant="warning" [progress]="75" label="Warning Small"></ui-progress-bar>
</div>
</div>
<!-- Large sizes -->
<div>
<h4>Large Size Variants</h4>
<div style="display: flex; flex-direction: column; gap: 1rem;">
<ui-progress-bar size="lg" variant="primary" [progress]="85" label="Primary Large"></ui-progress-bar>
<ui-progress-bar size="lg" variant="success" [progress]="60" label="Success Large"></ui-progress-bar>
<ui-progress-bar size="lg" variant="danger" [progress]="35" label="Danger Large"></ui-progress-bar>
</div>
</div>
</div>
</section>
<!-- Without Labels -->
<section style="margin-bottom: 3rem;">
<h3>Progress Bars without Labels</h3>
<div style="display: flex; flex-direction: column; gap: 1.5rem;">
<ui-progress-bar
[progress]="90"
variant="success"
[showLabel]="false"
ariaLabel="File upload progress">
</ui-progress-bar>
<ui-progress-bar
progressType="indeterminate"
variant="primary"
[showLabel]="false"
ariaLabel="Loading content">
</ui-progress-bar>
<ui-progress-bar
[progress]="45"
[buffer]="70"
progressType="buffer"
variant="secondary"
[showLabel]="false"
ariaLabel="Video buffering progress">
</ui-progress-bar>
</div>
</section>
<!-- Interactive Demo -->
<section style="margin-bottom: 3rem;">
<h3>Interactive Demo</h3>
<div style="display: flex; flex-wrap: wrap; gap: 2rem; margin-bottom: 2rem;">
<!-- Controls -->
<div style="display: flex; flex-direction: column; gap: 1rem; min-width: 200px;">
<div>
<label style="display: block; margin-bottom: 0.5rem; font-weight: bold;">Progress Value:</label>
<input
type="range"
min="0"
max="100"
[(ngModel)]="demoProgress"
style="width: 100%;">
<span style="font-size: 0.875rem; color: #666;">{{ demoProgress }}%</span>
</div>
<div>
<label style="display: block; margin-bottom: 0.5rem; font-weight: bold;">Buffer Value:</label>
<input
type="range"
min="0"
max="100"
[(ngModel)]="demoBuffer"
style="width: 100%;">
<span style="font-size: 0.875rem; color: #666;">{{ demoBuffer }}%</span>
</div>
<div>
<label style="display: block; margin-bottom: 0.5rem; font-weight: bold;">Size:</label>
<select [(ngModel)]="demoSize" style="padding: 0.5rem; border: 1px solid #ccc; border-radius: 4px; width: 100%;">
<option value="sm">Small</option>
<option value="md">Medium</option>
<option value="lg">Large</option>
</select>
</div>
<div>
<label style="display: block; margin-bottom: 0.5rem; font-weight: bold;">Variant:</label>
<select [(ngModel)]="demoVariant" style="padding: 0.5rem; border: 1px solid #ccc; border-radius: 4px; width: 100%;">
<option value="primary">Primary</option>
<option value="secondary">Secondary</option>
<option value="success">Success</option>
<option value="warning">Warning</option>
<option value="danger">Danger</option>
</select>
</div>
<div>
<label style="display: block; margin-bottom: 0.5rem; font-weight: bold;">Type:</label>
<select [(ngModel)]="demoType" style="padding: 0.5rem; border: 1px solid #ccc; border-radius: 4px; width: 100%;">
<option value="determinate">Determinate</option>
<option value="indeterminate">Indeterminate</option>
<option value="buffer">Buffer</option>
</select>
</div>
<div>
<label style="display: block; margin-bottom: 0.5rem; font-weight: bold;">Options:</label>
<div style="display: flex; flex-direction: column; gap: 0.25rem;">
<label style="font-size: 0.875rem;">
<input type="checkbox" [(ngModel)]="demoStriped" style="margin-right: 0.5rem;">
Striped
</label>
<label style="font-size: 0.875rem;">
<input type="checkbox" [(ngModel)]="demoAnimated" style="margin-right: 0.5rem;">
Animated
</label>
<label style="font-size: 0.875rem;">
<input type="checkbox" [(ngModel)]="demoShowPercentage" style="margin-right: 0.5rem;">
Show Percentage
</label>
<label style="font-size: 0.875rem;">
<input type="checkbox" [(ngModel)]="demoDisabled" style="margin-right: 0.5rem;">
Disabled
</label>
</div>
</div>
<div style="display: flex; gap: 0.5rem; margin-top: 1rem;">
<button (click)="startDemo()" style="padding: 0.5rem 1rem; border: 1px solid #007bff; border-radius: 4px; background: #007bff; color: white; cursor: pointer; flex: 1;">
Start Demo
</button>
<button (click)="resetDemo()" style="padding: 0.5rem 1rem; border: 1px solid #ccc; border-radius: 4px; background: white; cursor: pointer; flex: 1;">
Reset
</button>
</div>
</div>
<!-- Live Preview -->
<div style="flex: 1; min-width: 300px;">
<h4>Live Preview:</h4>
<div style="padding: 2rem; border: 2px dashed #ccc; border-radius: 8px; background: #fafafa;">
<ui-progress-bar
[size]="demoSize"
[variant]="demoVariant"
[progressType]="demoType"
[progress]="demoProgress"
[buffer]="demoBuffer"
[striped]="demoStriped"
[animated]="demoAnimated"
[showPercentage]="demoShowPercentage"
[state]="demoDisabled ? 'disabled' : 'default'"
label="Interactive Demo Progress"
helperText="Customize the progress bar using the controls">
</ui-progress-bar>
</div>
</div>
</div>
</section>
<!-- Usage Examples -->
<section style="margin-bottom: 3rem;">
<h3>Usage Examples</h3>
<div style="background: #f8f9fa; padding: 1.5rem; border-radius: 8px; border-left: 4px solid #007bff;">
<h4>Basic Progress Bar:</h4>
<pre style="background: #fff; padding: 1rem; border-radius: 4px; overflow-x: auto;"><code>&lt;ui-progress-bar
label="Download Progress"
size="md"
variant="primary"
[progress]="75"
helperText="3 of 4 files downloaded"&gt;
&lt;/ui-progress-bar&gt;</code></pre>
<h4>Indeterminate Progress:</h4>
<pre style="background: #fff; padding: 1rem; border-radius: 4px; overflow-x: auto;"><code>&lt;ui-progress-bar
label="Loading..."
progressType="indeterminate"
variant="primary"
[animated]="true"
helperText="Please wait while we process your request"&gt;
&lt;/ui-progress-bar&gt;</code></pre>
<h4>Buffer Progress:</h4>
<pre style="background: #fff; padding: 1rem; border-radius: 4px; overflow-x: auto;"><code>&lt;ui-progress-bar
label="Video Loading"
progressType="buffer"
[progress]="currentProgress"
[buffer]="bufferProgress"
variant="secondary"
helperText="Buffering video content"&gt;
&lt;/ui-progress-bar&gt;</code></pre>
<h4>Striped Animated Progress:</h4>
<pre style="background: #fff; padding: 1rem; border-radius: 4px; overflow-x: auto;"><code>&lt;ui-progress-bar
label="Upload Progress"
[progress]="uploadPercent"
variant="success"
[striped]="true"
[animated]="true"
size="lg"
helperText="Uploading files..."&gt;
&lt;/ui-progress-bar&gt;</code></pre>
</div>
</section>
<!-- Programmatic Control Example -->
<section style="margin-bottom: 3rem;">
<h3>Programmatic Control Example</h3>
<div style="display: flex; flex-direction: column; gap: 1rem;">
<ui-progress-bar
#programmableProgress
label="File Processing"
[progress]="programmableValue()"
variant="success"
helperText="Processing files..."
size="lg">
</ui-progress-bar>
<div style="display: flex; gap: 1rem; flex-wrap: wrap;">
<button (click)="simulateProgress()" style="padding: 0.5rem 1rem; border: 1px solid #28a745; border-radius: 4px; background: #28a745; color: white; cursor: pointer;">
Simulate Progress
</button>
<button (click)="pauseProgress()" style="padding: 0.5rem 1rem; border: 1px solid #ffc107; border-radius: 4px; background: #ffc107; color: black; cursor: pointer;">
Pause
</button>
<button (click)="resetProgrammable()" style="padding: 0.5rem 1rem; border: 1px solid #6c757d; border-radius: 4px; background: #6c757d; color: white; cursor: pointer;">
Reset
</button>
<button (click)="completeProgress()" style="padding: 0.5rem 1rem; border: 1px solid #007bff; border-radius: 4px; background: #007bff; color: white; cursor: pointer;">
Complete
</button>
</div>
<div style="font-size: 0.875rem; color: #666;">
<strong>Current Progress:</strong> {{ programmableValue() }}% |
<strong>Status:</strong> {{ progressStatus() }}
</div>
</div>
</section>
</div>
`,
styles: [`
h2 {
color: hsl(279, 14%, 11%);
font-size: 2rem;
margin-bottom: 2rem;
border-bottom: 2px solid hsl(258, 100%, 47%);
padding-bottom: 0.5rem;
}
h3 {
color: hsl(279, 14%, 25%);
font-size: 1.5rem;
margin-bottom: 1rem;
}
h4 {
color: hsl(287, 12%, 35%);
font-size: 1.125rem;
margin-bottom: 0.75rem;
}
section {
border: 1px solid hsl(289, 14%, 90%);
border-radius: 8px;
padding: 1.5rem;
background: hsl(286, 20%, 99%);
}
pre {
font-size: 0.875rem;
line-height: 1.5;
margin: 0.5rem 0;
}
code {
font-family: 'JetBrains Mono', monospace;
color: #d63384;
}
select, input[type="checkbox"], input[type="range"] {
cursor: pointer;
}
label {
cursor: pointer;
}
button:hover {
opacity: 0.9;
}
button:active {
transform: scale(0.98);
}
`]
})
export class ProgressDemoComponent {
// Animated progress values
determinateProgress = signal(35);
bufferProgress = signal(25);
bufferValue = signal(65);
// Interactive demo properties
demoProgress = 60;
demoBuffer = 80;
demoSize: 'sm' | 'md' | 'lg' = 'md';
demoVariant: 'primary' | 'secondary' | 'success' | 'warning' | 'danger' = 'primary';
demoType: 'determinate' | 'indeterminate' | 'buffer' = 'determinate';
demoStriped = false;
demoAnimated = false;
demoShowPercentage = true;
demoDisabled = false;
// Programmable progress
programmableValue = signal(0);
progressStatus = signal('Ready');
private progressInterval: any;
private isPaused = false;
ngOnInit(): void {
// Start some animated progress bars
this.animateProgress();
}
ngOnDestroy(): void {
if (this.progressInterval) {
clearInterval(this.progressInterval);
}
}
private animateProgress(): void {
// Animate the determinate progress
setInterval(() => {
const current = this.determinateProgress();
const next = (current + 1) % 101;
this.determinateProgress.set(next);
}, 100);
// Animate the buffer progress
setInterval(() => {
const currentBuffer = this.bufferValue();
const currentProgress = this.bufferProgress();
const nextBuffer = (currentBuffer + 0.5) % 101;
const nextProgress = Math.min(nextBuffer - 20, 100);
this.bufferValue.set(nextBuffer);
this.bufferProgress.set(Math.max(0, nextProgress));
}, 150);
}
startDemo(): void {
this.demoProgress = 0;
let progress = 0;
const interval = setInterval(() => {
progress += Math.random() * 3;
this.demoProgress = Math.min(100, progress);
if (progress >= 100) {
clearInterval(interval);
}
}, 100);
}
resetDemo(): void {
this.demoProgress = 0;
this.demoBuffer = 0;
this.demoSize = 'md';
this.demoVariant = 'primary';
this.demoType = 'determinate';
this.demoStriped = false;
this.demoAnimated = false;
this.demoShowPercentage = true;
this.demoDisabled = false;
}
simulateProgress(): void {
if (this.progressInterval) {
clearInterval(this.progressInterval);
}
this.isPaused = false;
this.progressStatus.set('Processing...');
this.progressInterval = setInterval(() => {
if (!this.isPaused) {
const current = this.programmableValue();
if (current < 100) {
this.programmableValue.set(current + Math.random() * 2);
} else {
this.progressStatus.set('Complete!');
clearInterval(this.progressInterval);
}
}
}, 50);
}
pauseProgress(): void {
this.isPaused = !this.isPaused;
this.progressStatus.set(this.isPaused ? 'Paused' : 'Processing...');
}
resetProgrammable(): void {
if (this.progressInterval) {
clearInterval(this.progressInterval);
}
this.programmableValue.set(0);
this.progressStatus.set('Ready');
this.isPaused = false;
}
completeProgress(): void {
if (this.progressInterval) {
clearInterval(this.progressInterval);
}
this.programmableValue.set(100);
this.progressStatus.set('Complete!');
this.isPaused = false;
}
}