import { Component, ChangeDetectionStrategy, input, model, inject } from '@angular/core'; import { NgIcon } from '@ng-icons/core'; import { DocumentationService } from '@core/services/documentation.service'; import { NewBadgeComponent } from '@ui/new-badge/new-badge.component'; import { generateControlId } from '@ui/control-id'; import { effectiveDisabled as computeEffectiveDisabled } from '@ui/effective-disabled'; @Component({ selector: 'app-toggle', standalone: true, imports: [NgIcon, NewBadgeComponent], templateUrl: './toggle.component.html', styleUrl: './toggle.component.scss', changeDetection: ChangeDetectionStrategy.OnPush, }) export class ToggleComponent { private readonly docs = inject(DocumentationService); protected readonly controlId = generateControlId('app-toggle'); label = input(); featureId = input(); disabled = input(false); forceDisabled = input(false); hint = input(); helpKey = input(); beforeChange = input<(newValue: boolean) => Promise | boolean>(); checked = model(false); readonly effectiveDisabled = computeEffectiveDisabled(this.disabled, this.forceDisabled); private pending = false; async toggle(): Promise { if (this.effectiveDisabled() || this.pending) return; const newValue = !this.checked(); const guard = this.beforeChange(); if (guard) { this.pending = true; try { const allowed = await guard(newValue); if (!allowed) return; } catch { return; } finally { this.pending = false; } } this.checked.set(newValue); } onKeydown(event: KeyboardEvent): void { if (event.key === ' ' || event.key === 'Enter') { event.preventDefault(); this.toggle(); } } onHelpClick(event: Event): void { event.preventDefault(); event.stopPropagation(); const key = this.helpKey(); if (key) { const [section, field] = key.split(':'); this.docs.openFieldDocumentation(section, field); } } }