- 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>
513 lines
15 KiB
TypeScript
513 lines
15 KiB
TypeScript
import { Component, signal } from '@angular/core';
|
|
import { CommonModule } from '@angular/common';
|
|
import { FormsModule, ReactiveFormsModule, FormBuilder, FormGroup } from '@angular/forms';
|
|
import { RangeSliderComponent, RangeSliderTickMark } from '../../../../../ui-essentials/src/public-api';
|
|
|
|
@Component({
|
|
selector: 'ui-range-slider-demo',
|
|
standalone: true,
|
|
imports: [CommonModule, FormsModule, ReactiveFormsModule, RangeSliderComponent],
|
|
template: `
|
|
<div class="demo-container">
|
|
<h2>Range Slider Demo</h2>
|
|
|
|
<!-- Size Variants -->
|
|
<section class="demo-section">
|
|
<h3>Sizes</h3>
|
|
<div class="demo-column">
|
|
@for (size of sizes; track size) {
|
|
<div class="demo-item">
|
|
<ui-range-slider
|
|
[size]="size"
|
|
[value]="75"
|
|
[label]="size.toUpperCase() + ' Size'"
|
|
[showValue]="true">
|
|
</ui-range-slider>
|
|
</div>
|
|
}
|
|
</div>
|
|
</section>
|
|
|
|
<!-- Color Variants -->
|
|
<section class="demo-section">
|
|
<h3>Variants</h3>
|
|
<div class="demo-column">
|
|
@for (variant of variants; track variant) {
|
|
<div class="demo-item">
|
|
<ui-range-slider
|
|
[variant]="variant"
|
|
[value]="65"
|
|
[label]="variant + ' variant'"
|
|
[showValue]="true">
|
|
</ui-range-slider>
|
|
</div>
|
|
}
|
|
</div>
|
|
</section>
|
|
|
|
<!-- States -->
|
|
<section class="demo-section">
|
|
<h3>States</h3>
|
|
<div class="demo-column">
|
|
<div class="demo-item">
|
|
<ui-range-slider
|
|
[value]="45"
|
|
label="Default State"
|
|
[showValue]="true">
|
|
</ui-range-slider>
|
|
</div>
|
|
|
|
<div class="demo-item">
|
|
<ui-range-slider
|
|
[disabled]="true"
|
|
[value]="45"
|
|
label="Disabled State"
|
|
[showValue]="true">
|
|
</ui-range-slider>
|
|
</div>
|
|
|
|
<div class="demo-item">
|
|
<ui-range-slider
|
|
[readonly]="true"
|
|
[value]="75"
|
|
label="Readonly State"
|
|
[showValue]="true">
|
|
</ui-range-slider>
|
|
</div>
|
|
|
|
<div class="demo-item">
|
|
<ui-range-slider
|
|
[value]="30"
|
|
[hasError]="true"
|
|
label="Error State"
|
|
helperText="This field has an error"
|
|
[showValue]="true">
|
|
</ui-range-slider>
|
|
</div>
|
|
</div>
|
|
</section>
|
|
|
|
<!-- Range Configurations -->
|
|
<section class="demo-section">
|
|
<h3>Range Configurations</h3>
|
|
<div class="demo-column">
|
|
<div class="demo-item">
|
|
<ui-range-slider
|
|
[min]="0"
|
|
[max]="100"
|
|
[step]="1"
|
|
[value]="50"
|
|
label="Standard (0-100, step 1)"
|
|
[showValue]="true">
|
|
</ui-range-slider>
|
|
</div>
|
|
|
|
<div class="demo-item">
|
|
<ui-range-slider
|
|
[min]="0"
|
|
[max]="10"
|
|
[step]="0.5"
|
|
[value]="7.5"
|
|
label="Decimal Steps (0-10, step 0.5)"
|
|
[showValue]="true">
|
|
</ui-range-slider>
|
|
</div>
|
|
|
|
<div class="demo-item">
|
|
<ui-range-slider
|
|
[min]="-50"
|
|
[max]="50"
|
|
[step]="5"
|
|
[value]="-10"
|
|
label="Negative Range (-50 to 50, step 5)"
|
|
[showValue]="true">
|
|
</ui-range-slider>
|
|
</div>
|
|
|
|
<div class="demo-item">
|
|
<ui-range-slider
|
|
[min]="1000"
|
|
[max]="10000"
|
|
[step]="100"
|
|
[value]="5500"
|
|
label="Large Numbers (1K-10K)"
|
|
[showValue]="true"
|
|
valueUnit=" units">
|
|
</ui-range-slider>
|
|
</div>
|
|
</div>
|
|
</section>
|
|
|
|
<!-- With Tick Marks -->
|
|
<section class="demo-section">
|
|
<h3>Tick Marks</h3>
|
|
<div class="demo-column">
|
|
<div class="demo-item">
|
|
<ui-range-slider
|
|
[min]="0"
|
|
[max]="100"
|
|
[step]="10"
|
|
[value]="60"
|
|
[ticks]="basicTicks"
|
|
label="Basic Tick Marks"
|
|
[showValue]="true">
|
|
</ui-range-slider>
|
|
</div>
|
|
|
|
<div class="demo-item">
|
|
<ui-range-slider
|
|
[min]="0"
|
|
[max]="5"
|
|
[step]="1"
|
|
[value]="3"
|
|
[ticks]="labeledTicks"
|
|
[showTickLabels]="true"
|
|
label="Labeled Tick Marks"
|
|
[showValue]="true">
|
|
</ui-range-slider>
|
|
</div>
|
|
|
|
<div class="demo-item">
|
|
<ui-range-slider
|
|
[min]="0"
|
|
[max]="100"
|
|
[step]="5"
|
|
[value]="75"
|
|
[ticks]="majorMinorTicks"
|
|
[showTickLabels]="true"
|
|
label="Major & Minor Ticks"
|
|
[showValue]="true">
|
|
</ui-range-slider>
|
|
</div>
|
|
</div>
|
|
</section>
|
|
|
|
<!-- Interactive Example -->
|
|
<section class="demo-section">
|
|
<h3>Interactive Configuration</h3>
|
|
<div class="demo-controls">
|
|
<div class="control-row">
|
|
<div class="control-group">
|
|
<label>Min Value: {{ interactiveMin() }}</label>
|
|
<input
|
|
type="range"
|
|
min="-100"
|
|
max="100"
|
|
[value]="interactiveMin()"
|
|
(input)="updateMin($event)" />
|
|
</div>
|
|
|
|
<div class="control-group">
|
|
<label>Max Value: {{ interactiveMax() }}</label>
|
|
<input
|
|
type="range"
|
|
min="0"
|
|
max="200"
|
|
[value]="interactiveMax()"
|
|
(input)="updateMax($event)" />
|
|
</div>
|
|
|
|
<div class="control-group">
|
|
<label>Step: {{ interactiveStep() }}</label>
|
|
<select [value]="interactiveStep()" (change)="updateStep($event)">
|
|
<option value="1">1</option>
|
|
<option value="5">5</option>
|
|
<option value="10">10</option>
|
|
<option value="0.1">0.1</option>
|
|
<option value="0.5">0.5</option>
|
|
</select>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="control-row">
|
|
<div class="control-group">
|
|
<label>Size:</label>
|
|
<select [value]="interactiveSize()" (change)="updateSize($event)">
|
|
@for (size of sizes; track size) {
|
|
<option [value]="size">{{ size }}</option>
|
|
}
|
|
</select>
|
|
</div>
|
|
|
|
<div class="control-group">
|
|
<label>Variant:</label>
|
|
<select [value]="interactiveVariant()" (change)="updateVariant($event)">
|
|
@for (variant of variants; track variant) {
|
|
<option [value]="variant">{{ variant }}</option>
|
|
}
|
|
</select>
|
|
</div>
|
|
|
|
<div class="control-group">
|
|
<label>
|
|
<input
|
|
type="checkbox"
|
|
[checked]="interactiveShowValue()"
|
|
(change)="toggleShowValue($event)" />
|
|
Show Value
|
|
</label>
|
|
</div>
|
|
|
|
<div class="control-group">
|
|
<label>
|
|
<input
|
|
type="checkbox"
|
|
[checked]="interactiveDisabled()"
|
|
(change)="toggleDisabled($event)" />
|
|
Disabled
|
|
</label>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="demo-interactive-result">
|
|
<ui-range-slider
|
|
[min]="interactiveMin()"
|
|
[max]="interactiveMax()"
|
|
[step]="interactiveStep()"
|
|
[value]="interactiveValue()"
|
|
[size]="interactiveSize()"
|
|
[variant]="interactiveVariant()"
|
|
[showValue]="interactiveShowValue()"
|
|
[disabled]="interactiveDisabled()"
|
|
label="Interactive Slider"
|
|
helperText="Customize using controls above"
|
|
(valueChange)="onInteractiveValueChange($event)">
|
|
</ui-range-slider>
|
|
</div>
|
|
</section>
|
|
|
|
<!-- Form Integration -->
|
|
<section class="demo-section">
|
|
<h3>Form Integration</h3>
|
|
<form [formGroup]="demoForm" class="demo-form">
|
|
<div class="form-row">
|
|
<ui-range-slider
|
|
formControlName="volume"
|
|
[min]="0"
|
|
[max]="100"
|
|
[step]="1"
|
|
label="Volume"
|
|
[showValue]="true"
|
|
valueUnit="%"
|
|
helperText="Adjust the volume level">
|
|
</ui-range-slider>
|
|
</div>
|
|
|
|
<div class="form-row">
|
|
<ui-range-slider
|
|
formControlName="brightness"
|
|
[min]="0"
|
|
[max]="255"
|
|
[step]="5"
|
|
label="Brightness"
|
|
[showValue]="true"
|
|
variant="secondary"
|
|
helperText="Screen brightness setting">
|
|
</ui-range-slider>
|
|
</div>
|
|
|
|
<div class="form-row">
|
|
<ui-range-slider
|
|
formControlName="temperature"
|
|
[min]="16"
|
|
[max]="30"
|
|
[step]="0.5"
|
|
[ticks]="temperatureTicks"
|
|
[showTickLabels]="true"
|
|
label="Temperature"
|
|
[showValue]="true"
|
|
valueUnit="°C"
|
|
variant="warning">
|
|
</ui-range-slider>
|
|
</div>
|
|
|
|
<div class="form-output">
|
|
<h4>Form Values:</h4>
|
|
<pre>{{ getFormValues() | json }}</pre>
|
|
</div>
|
|
</form>
|
|
</section>
|
|
|
|
<!-- Event Demonstration -->
|
|
<section class="demo-section">
|
|
<h3>Event Handling</h3>
|
|
<div class="demo-column">
|
|
<div class="demo-item">
|
|
<ui-range-slider
|
|
[value]="eventSliderValue()"
|
|
label="Event Slider"
|
|
[showValue]="true"
|
|
(valueChange)="onValueChange($event)"
|
|
(slideStart)="onSlideStart($event)"
|
|
(slideEnd)="onSlideEnd($event)"
|
|
(sliderFocus)="onSliderFocus()"
|
|
(sliderBlur)="onSliderBlur()">
|
|
</ui-range-slider>
|
|
</div>
|
|
|
|
<div class="event-log">
|
|
<h4>Event Log:</h4>
|
|
<div class="event-list">
|
|
@for (event of eventLog(); track $index) {
|
|
<div class="event-item">{{ event }}</div>
|
|
}
|
|
</div>
|
|
<button (click)="clearEventLog()">Clear Log</button>
|
|
</div>
|
|
</div>
|
|
</section>
|
|
</div>
|
|
`,
|
|
styleUrl: './range-slider-demo.component.scss'
|
|
})
|
|
export class RangeSliderDemoComponent {
|
|
private fb = new FormBuilder();
|
|
|
|
sizes = ['sm', 'md', 'lg'] as const;
|
|
variants = ['primary', 'secondary', 'success', 'warning', 'danger'] as const;
|
|
|
|
// Interactive demo state
|
|
interactiveValue = signal(50);
|
|
interactiveMin = signal(0);
|
|
interactiveMax = signal(100);
|
|
interactiveStep = signal(1);
|
|
interactiveSize = signal<'sm' | 'md' | 'lg'>('md');
|
|
interactiveVariant = signal<'primary' | 'secondary' | 'success' | 'warning' | 'danger'>('primary');
|
|
interactiveShowValue = signal(true);
|
|
interactiveDisabled = signal(false);
|
|
|
|
// Event demo state
|
|
eventSliderValue = signal(25);
|
|
eventLog = signal<string[]>([]);
|
|
|
|
// Tick mark configurations
|
|
basicTicks: RangeSliderTickMark[] = [
|
|
{ value: 0 },
|
|
{ value: 25 },
|
|
{ value: 50 },
|
|
{ value: 75 },
|
|
{ value: 100 }
|
|
];
|
|
|
|
labeledTicks: RangeSliderTickMark[] = [
|
|
{ value: 0, label: 'Min' },
|
|
{ value: 1, label: 'Low' },
|
|
{ value: 2, label: 'Med' },
|
|
{ value: 3, label: 'High' },
|
|
{ value: 4, label: 'Very High' },
|
|
{ value: 5, label: 'Max' }
|
|
];
|
|
|
|
majorMinorTicks: RangeSliderTickMark[] = [
|
|
{ value: 0, label: '0%', major: true },
|
|
{ value: 25, major: false },
|
|
{ value: 50, label: '50%', major: true },
|
|
{ value: 75, major: false },
|
|
{ value: 100, label: '100%', major: true }
|
|
];
|
|
|
|
temperatureTicks: RangeSliderTickMark[] = [
|
|
{ value: 16, label: '16°' },
|
|
{ value: 18, label: '18°' },
|
|
{ value: 20, label: '20°' },
|
|
{ value: 22, label: '22°' },
|
|
{ value: 24, label: '24°' },
|
|
{ value: 26, label: '26°' },
|
|
{ value: 28, label: '28°' },
|
|
{ value: 30, label: '30°' }
|
|
];
|
|
|
|
// Form setup
|
|
demoForm: FormGroup = this.fb.group({
|
|
volume: [75],
|
|
brightness: [128],
|
|
temperature: [22]
|
|
});
|
|
|
|
// Interactive controls
|
|
updateMin(event: Event): void {
|
|
const target = event.target as HTMLInputElement;
|
|
const newMin = parseInt(target.value, 10);
|
|
this.interactiveMin.set(newMin);
|
|
// Adjust value if it's now below min
|
|
if (this.interactiveValue() < newMin) {
|
|
this.interactiveValue.set(newMin);
|
|
}
|
|
}
|
|
|
|
updateMax(event: Event): void {
|
|
const target = event.target as HTMLInputElement;
|
|
const newMax = parseInt(target.value, 10);
|
|
this.interactiveMax.set(newMax);
|
|
// Adjust value if it's now above max
|
|
if (this.interactiveValue() > newMax) {
|
|
this.interactiveValue.set(newMax);
|
|
}
|
|
}
|
|
|
|
updateStep(event: Event): void {
|
|
const target = event.target as HTMLSelectElement;
|
|
this.interactiveStep.set(parseFloat(target.value));
|
|
}
|
|
|
|
updateSize(event: Event): void {
|
|
const target = event.target as HTMLSelectElement;
|
|
this.interactiveSize.set(target.value as any);
|
|
}
|
|
|
|
updateVariant(event: Event): void {
|
|
const target = event.target as HTMLSelectElement;
|
|
this.interactiveVariant.set(target.value as any);
|
|
}
|
|
|
|
toggleShowValue(event: Event): void {
|
|
const target = event.target as HTMLInputElement;
|
|
this.interactiveShowValue.set(target.checked);
|
|
}
|
|
|
|
toggleDisabled(event: Event): void {
|
|
const target = event.target as HTMLInputElement;
|
|
this.interactiveDisabled.set(target.checked);
|
|
}
|
|
|
|
onInteractiveValueChange(value: number): void {
|
|
this.interactiveValue.set(value);
|
|
}
|
|
|
|
// Event handlers
|
|
onValueChange(value: number): void {
|
|
this.eventSliderValue.set(value);
|
|
this.addEventLog(`Value changed: ${value}`);
|
|
}
|
|
|
|
onSlideStart(value: number): void {
|
|
this.addEventLog(`Slide started at: ${value}`);
|
|
}
|
|
|
|
onSlideEnd(value: number): void {
|
|
this.addEventLog(`Slide ended at: ${value}`);
|
|
}
|
|
|
|
onSliderFocus(): void {
|
|
this.addEventLog('Slider focused');
|
|
}
|
|
|
|
onSliderBlur(): void {
|
|
this.addEventLog('Slider blurred');
|
|
}
|
|
|
|
private addEventLog(message: string): void {
|
|
const timestamp = new Date().toLocaleTimeString();
|
|
const newLog = `[${timestamp}] ${message}`;
|
|
this.eventLog.update(log => [newLog, ...log.slice(0, 9)]); // Keep last 10 events
|
|
}
|
|
|
|
clearEventLog(): void {
|
|
this.eventLog.set([]);
|
|
}
|
|
|
|
getFormValues(): any {
|
|
return this.demoForm.value;
|
|
}
|
|
} |