Initial commit: timeline-elements-ui library
Angular 19 component library for timelines and event tracking: timeline, Gantt chart, event cards, date markers, connectors, and custom event templates. Includes signal-based services, SCSS design tokens with dark mode, and TypeScript type definitions. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,92 @@
|
||||
import { Component, ChangeDetectionStrategy, Input, Output, EventEmitter, ViewChild, ElementRef, AfterViewInit } from '@angular/core';
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { ButtonComponent, IconComponent, SkeletonComponent, TooltipDirective } from '@sda/base-ui';
|
||||
import type { TlTimelineItem } from '../../types/timeline.types';
|
||||
import type { TlMarkerSize, TlConnectorStyle, TlSortDirection } from '../../types/config.types';
|
||||
import type { TlTimelineItemClickEvent } from '../../types/event.types';
|
||||
import { formatSmartTime } from '../../utils/date.utils';
|
||||
|
||||
@Component({
|
||||
selector: 'tl-horizontal-timeline',
|
||||
standalone: true,
|
||||
imports: [CommonModule, ButtonComponent, IconComponent, SkeletonComponent, TooltipDirective],
|
||||
templateUrl: './tl-horizontal-timeline.component.html',
|
||||
styleUrl: './tl-horizontal-timeline.component.scss',
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
})
|
||||
export class TlHorizontalTimelineComponent implements AfterViewInit {
|
||||
@ViewChild('scrollContainer') scrollContainer?: ElementRef<HTMLDivElement>;
|
||||
|
||||
@Input({ required: true }) items!: TlTimelineItem[];
|
||||
@Input() markerSize: TlMarkerSize = 'md';
|
||||
@Input() connectorStyle: TlConnectorStyle = 'solid';
|
||||
@Input() sortDirection: TlSortDirection = 'desc';
|
||||
@Input() scrollable = true;
|
||||
@Input() showNavArrows = true;
|
||||
@Input() loading = false;
|
||||
@Input() emptyMessage = 'No timeline items';
|
||||
|
||||
@Output() itemClick = new EventEmitter<TlTimelineItemClickEvent>();
|
||||
|
||||
protected canScrollLeft = false;
|
||||
protected canScrollRight = false;
|
||||
|
||||
protected get sortedItems(): TlTimelineItem[] {
|
||||
const items = [...this.items];
|
||||
const direction = this.sortDirection;
|
||||
|
||||
items.sort((a, b) => {
|
||||
const aTime = new Date(a.date).getTime();
|
||||
const bTime = new Date(b.date).getTime();
|
||||
return direction === 'asc' ? aTime - bTime : bTime - aTime;
|
||||
});
|
||||
|
||||
return items;
|
||||
}
|
||||
|
||||
ngAfterViewInit(): void {
|
||||
this.updateScrollState();
|
||||
}
|
||||
|
||||
protected formatTime(item: TlTimelineItem): string {
|
||||
return formatSmartTime(item.date);
|
||||
}
|
||||
|
||||
protected getMarkerColor(item: TlTimelineItem): string {
|
||||
if (item.iconColor) return item.iconColor;
|
||||
if (item.status) return `var(--tl-status-${item.status})`;
|
||||
return 'var(--tl-marker-bg)';
|
||||
}
|
||||
|
||||
protected onItemClick(item: TlTimelineItem, index: number): void {
|
||||
this.itemClick.emit({ item, index });
|
||||
}
|
||||
|
||||
protected scrollLeft(): void {
|
||||
const container = this.scrollContainer?.nativeElement;
|
||||
if (container) {
|
||||
container.scrollBy({ left: -200, behavior: 'smooth' });
|
||||
setTimeout(() => this.updateScrollState(), 300);
|
||||
}
|
||||
}
|
||||
|
||||
protected scrollRight(): void {
|
||||
const container = this.scrollContainer?.nativeElement;
|
||||
if (container) {
|
||||
container.scrollBy({ left: 200, behavior: 'smooth' });
|
||||
setTimeout(() => this.updateScrollState(), 300);
|
||||
}
|
||||
}
|
||||
|
||||
protected updateScrollState(): void {
|
||||
const container = this.scrollContainer?.nativeElement;
|
||||
if (container) {
|
||||
this.canScrollLeft = container.scrollLeft > 0;
|
||||
this.canScrollRight = container.scrollLeft < container.scrollWidth - container.clientWidth - 1;
|
||||
}
|
||||
}
|
||||
|
||||
protected getLoadingItems(): number[] {
|
||||
return Array.from({ length: 5 }, (_, i) => i);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user