import { booleanAttribute, ChangeDetectionStrategy, Component, computed, inject, input, output, } from '@angular/core'; import { AfricaniesUiI18n } from '../i18n/africanies-ui-i18n'; import { AfricaniesIconComponent } from '@africanies/africanies-icons'; import { ActionMenuComponent, ActionMenuTriggerDirective, } from '../action-menu'; import type { AfricaniesMenuItem } from '../action-menu/menu-item'; import { ButtonComponent } from '../button/button.component'; import { flagCdnUrl } from './flag-cdn'; import type { LanguageSwitcherOption } from './language-switcher-option'; /** * Compact language menu with circular flagcdn (or custom) flags on the trigger * and each option row. Hosts own dictionaries and persistence; this only emits * the selected code. * * @example * ```html * * ``` */ @Component({ selector: 'africanies-language-switcher', standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, imports: [ ActionMenuComponent, ActionMenuTriggerDirective, AfricaniesIconComponent, ButtonComponent, ], template: ` `, }) /** * Compact language menu with circular flag prefixes and an optional caret. */ export class LanguageSwitcherComponent { private readonly i18n = inject(AfricaniesUiI18n); protected readonly resolvedAriaLabel = computed(() => { const label = this.ariaLabel(); return label === 'Language' ? this.i18n.t('africaniesUi.language.ariaLabel', 'Language') : label; }); /** Available languages (order preserved in the menu). */ readonly options = input.required(); /** Active language code. */ readonly value = input.required(); /** Accessible name for the trigger and menu. */ readonly ariaLabel = input('Language'); readonly disabled = input(false, { transform: booleanAttribute }); /** * When true (default), show the active label beside the flag on `sm+` * viewports. The flag always remains. */ readonly showLabel = input(true, { transform: booleanAttribute }); /** When true (default), show a chevron after the label. */ readonly showCaret = input(true, { transform: booleanAttribute }); /** Emits the chosen language code when the user picks a row. */ readonly valueChange = output(); protected readonly activeOption = computed(() => { const code = this.value(); return this.options().find((option) => option.code === code) ?? null; }); protected readonly activeFlagUrl = computed(() => { const option = this.activeOption(); return option ? resolveFlagUrl(option) : null; }); protected readonly activeLabel = computed( () => this.activeOption()?.label ?? this.value(), ); protected readonly menuItems = computed((): AfricaniesMenuItem[] => this.options().map((option) => ({ label: option.label, imageUrl: resolveFlagUrl(option) ?? undefined, imageShape: 'circle', onClick: () => this.valueChange.emit(option.code), })), ); } function resolveFlagUrl(option: LanguageSwitcherOption): string | null { if (option.flagUrl) { return option.flagUrl; } if (option.flagCountryCode) { return flagCdnUrl(option.flagCountryCode); } return null; }