Files
timeline-elements-ui/src/components/tl-changelog-version/tl-changelog-version.component.ts
Giuliano Silvestro a07edd485b 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>
2026-02-13 21:58:25 +10:00

83 lines
2.8 KiB
TypeScript

import { Component, ChangeDetectionStrategy, input, output, computed, signal } from '@angular/core';
import { TitleCasePipe } from '@angular/common';
import { BadgeComponent, IconComponent, ButtonComponent } from '@sda/base-ui';
import type { TlChangelogVersion, TlChangeCategory } from '../../types/changelog.types';
import type { TlVersionClickEvent, TlChangelogEntryClickEvent } from '../../types/event.types';
import { formatDate } from '../../utils/date.utils';
@Component({
selector: 'tl-changelog-version',
standalone: true,
imports: [BadgeComponent, IconComponent, ButtonComponent, TitleCasePipe],
templateUrl: './tl-changelog-version.component.html',
styleUrl: './tl-changelog-version.component.scss',
changeDetection: ChangeDetectionStrategy.OnPush,
host: {
'[class.tl-changelog-version--collapsible]': 'collapsible()',
'[class.tl-changelog-version--expanded]': 'isExpanded()',
},
})
export class TlChangelogVersionComponent {
readonly version = input.required<TlChangelogVersion>();
readonly collapsible = input(false);
readonly expanded = input(true);
readonly showCategoryBadges = input(true);
readonly showBreakingBadge = input(true);
readonly versionClick = output<TlVersionClickEvent>();
readonly entryClick = output<TlChangelogEntryClickEvent>();
readonly expandToggle = output<boolean>();
protected readonly isExpanded = signal(true);
protected readonly formattedDate = computed(() => formatDate(this.version().date));
protected readonly entriesByCategory = computed(() => {
const entries = this.version().entries;
const categories: TlChangeCategory[] = ['added', 'changed', 'fixed', 'removed', 'deprecated', 'security'];
return categories
.map(category => ({
category,
entries: entries.filter(e => e.category === category),
}))
.filter(group => group.entries.length > 0);
});
protected readonly categoryColor = computed(() => {
return (category: TlChangeCategory): string => {
return `var(--tl-change-${category})`;
};
});
protected readonly categoryIcon = computed(() => {
return (category: TlChangeCategory): string => {
switch (category) {
case 'added': return 'plus';
case 'changed': return 'edit';
case 'fixed': return 'check';
case 'removed': return 'minus';
case 'deprecated': return 'alert-triangle';
case 'security': return 'shield';
default: return 'circle';
}
};
});
protected onVersionClick(): void {
this.versionClick.emit({ version: this.version() });
if (this.collapsible()) {
this.toggleExpand();
}
}
protected toggleExpand(): void {
this.isExpanded.update(v => !v);
this.expandToggle.emit(this.isExpanded());
}
protected onEntryClick(entry: any): void {
this.entryClick.emit({ entry, version: this.version() });
}
}