chore: update Angular cache and TypeScript build info files

This commit is contained in:
Bruno Charest 2025-09-20 23:18:42 -04:00
parent 3f04191623
commit 5d6aa17b81
6 changed files with 116 additions and 40 deletions

File diff suppressed because one or more lines are too long

Binary file not shown.

View File

@ -251,37 +251,40 @@ export class HeaderComponent {
}
// Theme helpers for styling based on current theme
private resolveThemeSlug(slug: string | null | undefined): 'light' | 'dark' | 'black' | 'blue' | 'system' {
const v = (slug || 'system') as string;
if (v === 'system') return (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) ? 'dark' : 'light';
if (v === 'light' || v === 'dark' || v === 'black' || v === 'blue') return v;
return 'light';
}
getCurrentTheme(): string {
return this.currentTheme() || 'system';
}
isLightTheme(): boolean {
const t = this.getCurrentTheme();
return t === 'light' || t === 'system';
return this.resolveThemeSlug(this.getCurrentTheme()) === 'light';
}
isDarkTheme(): boolean {
const t = this.getCurrentTheme();
return t === 'dark';
return this.resolveThemeSlug(this.getCurrentTheme()) === 'dark';
}
isBlackTheme(): boolean {
const t = this.getCurrentTheme();
return t === 'black';
return this.resolveThemeSlug(this.getCurrentTheme()) === 'black';
}
isBlueTheme(): boolean {
const t = this.getCurrentTheme();
return t === 'blue';
return this.resolveThemeSlug(this.getCurrentTheme()) === 'blue';
}
getThemeClasses(): { [key: string]: boolean } {
const theme = this.getCurrentTheme();
const rt = this.resolveThemeSlug(this.getCurrentTheme());
return {
'theme-light': theme === 'light' || theme === 'system',
'theme-dark': theme === 'dark',
'theme-black': theme === 'black',
'theme-blue': theme === 'blue'
'theme-light': rt === 'light',
'theme-dark': rt === 'dark',
'theme-black': rt === 'black',
'theme-blue': rt === 'blue'
};
}

View File

@ -1,16 +1,15 @@
<nav class="sticky top-16 left-0 right-0 z-40 w-full relative"
[ngClass]="{
'bg-slate-100 border-b border-slate-200': isLightTheme(),
'bg-slate-900 border-b border-slate-800': isDarkTheme(),
'bg-black border-b border-slate-900': isBlackTheme(),
'bg-blue-950 border-b border-blue-900': isBlueTheme()
'bg-slate-800 border-b border-slate-700': isDarkTheme(),
'bg-slate-900 border-b border-slate-800': isBlackTheme(),
'bg-slate-700 border-b border-slate-600': isBlueTheme()
}">
<!-- Left scroll button -->
<button type="button" (click)="scrollBy(-320)" aria-label="Scroll left"
class="hidden md:flex items-center justify-center absolute left-2 top-1/2 -translate-y-1/2 h-9 w-9 rounded-full shadow z-10"
[ngClass]="{
'bg-white/90 border border-slate-300 text-slate-700 hover:bg-slate-100': isLightTheme(),
'bg-slate-800/90 border border-slate-700 text-slate-200 hover:bg-slate-700': !isLightTheme()
'bg-slate-800/90 border border-slate-700 text-slate-200 hover:bg-slate-700': isDarkTheme() || isBlackTheme() || isBlueTheme()
}">
«
</button>
@ -20,7 +19,7 @@
class="hidden md:flex items-center justify-center absolute right-2 top-1/2 -translate-y-1/2 h-9 w-9 rounded-full shadow z-10"
[ngClass]="{
'bg-white/90 border border-slate-300 text-slate-700 hover:bg-slate-100': isLightTheme(),
'bg-slate-800/90 border border-slate-700 text-slate-200 hover:bg-slate-700': !isLightTheme()
'bg-slate-800/90 border border-slate-700 text-slate-200 hover:bg-slate-700': isDarkTheme() || isBlackTheme() || isBlueTheme()
}">
»
</button>

View File

@ -0,0 +1,50 @@
<nav class="sticky top-16 left-0 right-0 z-40 w-full relative"
[ngClass]="{
'bg-slate-800 border-b border-slate-700': isDarkTheme(),
'bg-slate-900 border-b border-slate-800': isBlackTheme(),
'bg-slate-700 border-b border-slate-600': isBlueTheme()
}">
<!-- Left scroll button -->
<button type="button" (click)="scrollBy(-320)" aria-label="Scroll left"
class="hidden md:flex items-center justify-center absolute left-2 top-1/2 -translate-y-1/2 h-9 w-9 rounded-full shadow z-10"
[ngClass]="{
'bg-white/90 border border-slate-300 text-slate-700 hover:bg-slate-100': isLightTheme(),
'bg-slate-800/90 border border-slate-700 text-slate-200 hover:bg-slate-700': !isLightTheme()
}">
«
</button>
<!-- Right scroll button -->
<button type="button" (click)="scrollBy(320)" aria-label="Scroll right"
class="hidden md:flex items-center justify-center absolute right-2 top-1/2 -translate-y-1/2 h-9 w-9 rounded-full shadow z-10"
[ngClass]="{
'bg-white/90 border border-slate-300 text-slate-700 hover:bg-slate-100': isLightTheme(),
'bg-slate-800/90 border border-slate-700 text-slate-200 hover:bg-slate-700': !isLightTheme()
}">
»
</button>
<div class="w-full overflow-x-auto no-scrollbar" #scroll (wheel)="onWheel($event)">
<ul role="tablist" aria-label="Themes" class="flex gap-2 px-12 py-2 min-w-max items-center">
<li *ngFor="let t of displayedThemes(); let i = index" class="shrink-0">
<button
#pill
role="tab"
type="button"
class="px-3 py-1.5 rounded-full text-sm font-medium border transition-colors whitespace-nowrap focus:outline-none focus:ring-2 focus:ring-red-500"
[class.bg-slate-100/10]="activeSlug() === t.slug"
[class.text-white]="activeSlug() === t.slug"
[class.border-red-500]="activeSlug() === t.slug"
[class.text-slate-300]="activeSlug() !== t.slug"
[class.border-slate-700]="activeSlug() !== t.slug"
[attr.aria-selected]="activeSlug() === t.slug"
(click)="goToTheme(t.slug)"
(keydown)="onKeydown($event, i)"
>
<span class="mr-1 select-none">{{ t.emoji }}</span>
<span>{{ themesSvc.i18nLabel(t) }}</span>
</button>
</li>
</ul>
</div>
</nav>

View File

@ -1,4 +1,4 @@
import { ChangeDetectionStrategy, Component, ElementRef, QueryList, ViewChild, ViewChildren, inject, signal, effect } from '@angular/core';
import { ChangeDetectionStrategy, Component, ElementRef, QueryList, ViewChild, ViewChildren, inject, signal, effect, OnInit, OnDestroy } from '@angular/core';
import { CommonModule } from '@angular/common';
import { Router, NavigationEnd, ActivatedRoute } from '@angular/router';
import { ThemesService } from '../../services/themes.service';
@ -10,7 +10,7 @@ import { ThemesService } from '../../services/themes.service';
imports: [CommonModule],
templateUrl: './themes-nav.component.html'
})
export class ThemesNavComponent {
export class ThemesNavComponent implements OnDestroy {
private router = inject(Router);
private route = inject(ActivatedRoute);
themesSvc = inject(ThemesService);
@ -22,6 +22,9 @@ export class ThemesNavComponent {
@ViewChildren('pill', { read: ElementRef }) pills!: QueryList<ElementRef<HTMLButtonElement>>;
@ViewChild('scroll', { static: false }) scrollRef?: ElementRef<HTMLDivElement>;
// Signal to force re-evaluation when data-theme changes
private themeChanged = signal<number>(0);
constructor() {
// Reflect current URL into active slug
this.router.events.subscribe((e) => {
@ -29,6 +32,17 @@ export class ThemesNavComponent {
});
// Also on init
setTimeout(() => this.syncFromUrl(), 0);
// Effect to listen for theme changes on document.documentElement
effect(() => {
const currentTheme = document.documentElement.getAttribute('data-theme') || 'system';
// Trigger re-evaluation when theme changes
this.themeChanged.update(n => n + 1);
});
}
ngOnDestroy() {
// Nothing to cleanup
}
private syncFromUrl() {
@ -75,30 +89,40 @@ export class ThemesNavComponent {
}
// Theme helpers (read from document attribute/localStorage)
private getCurrentTheme(): string {
private getCurrentTheme(): 'light' | 'dark' | 'black' | 'blue' | 'system' {
try {
const fromAttr = document.documentElement.getAttribute('data-theme');
if (fromAttr) return fromAttr;
if (fromAttr) return fromAttr as any;
const fromStorage = localStorage.getItem('newtube.theme');
const val = fromStorage || 'system';
if (val === 'system') {
// Resolve to light/dark using media query so styles can be deterministic
const prefersDark = window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches;
return prefersDark ? 'dark' : 'light';
}
return val;
return (fromStorage as any) || 'system';
} catch {
// Safe fallback: prefer dark for safety in most UIs
const prefersDark = typeof window !== 'undefined' && (window.matchMedia?.('(prefers-color-scheme: dark)').matches ?? false);
return prefersDark ? 'dark' : 'light';
return 'system';
}
}
isLightTheme(): boolean {
const t = this.getCurrentTheme();
return t === 'light' || t === 'system';
private resolveThemeSlug(): 'light' | 'dark' | 'black' | 'blue' {
const cur = this.getCurrentTheme();
if (cur === 'system') {
const prefersDark = typeof window !== 'undefined' && window.matchMedia?.('(prefers-color-scheme: dark)').matches;
return prefersDark ? 'dark' : 'light';
}
return cur as any;
}
isLightTheme(): boolean {
this.themeChanged(); // Trigger re-evaluation
return this.resolveThemeSlug() === 'light';
}
isDarkTheme(): boolean {
this.themeChanged(); // Trigger re-evaluation
return this.resolveThemeSlug() === 'dark';
}
isBlackTheme(): boolean {
this.themeChanged(); // Trigger re-evaluation
return this.resolveThemeSlug() === 'black';
}
isBlueTheme(): boolean {
this.themeChanged(); // Trigger re-evaluation
return this.resolveThemeSlug() === 'blue';
}
isDarkTheme(): boolean { return this.getCurrentTheme() === 'dark'; }
isBlackTheme(): boolean { return this.getCurrentTheme() === 'black'; }
isBlueTheme(): boolean { return this.getCurrentTheme() === 'blue'; }
}