Press n or j to go to the next uncovered block, b, p or k for the previous block.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 | 1x 1x 13x 13x 13x 13x 13x 13x 13x 13x 13x 17x 13x 13x 5x 5x 5x 5x 5x 5x 5x 1x 5x 17x 3x 3x 3x | /** * Copyright (c) Siemens 2016 - 2025 * SPDX-License-Identifier: MIT */ import { A11yModule, CdkTrapFocus } from '@angular/cdk/a11y'; import { ChangeDetectionStrategy, Component, ElementRef, inject, input, OnDestroy, signal, viewChild } from '@angular/core'; import { SI_HEADER_DROPDOWN_OPTIONS } from '@siemens/element-ng/header-dropdown'; import { addIcons, elementOptionsVertical, SiIconComponent } from '@siemens/element-ng/icon'; import { SiTranslatePipe, t } from '@siemens/element-translate-ng/translate'; import { Subscription } from 'rxjs'; import { skip, takeUntil } from 'rxjs/operators'; import { SiApplicationHeaderComponent } from './si-application-header.component'; /** Container for actions that should be collapsed in mobile mode. */ @Component({ selector: 'si-header-collapsible-actions', imports: [SiTranslatePipe, A11yModule, SiIconComponent], templateUrl: './si-header-collapsible-actions.component.html', styles: '.badge-dot::after { inset-inline-end: 4px; }', providers: [ { provide: SI_HEADER_DROPDOWN_OPTIONS, useValue: { disableRootFocusTrapForInlineMode: true } } ], changeDetection: ChangeDetectionStrategy.OnPush, host: { class: 'd-contents' } }) export class SiHeaderCollapsibleActionsComponent implements OnDestroy { private static idCounter = 0; /** * Accessible label of the toggle button if actions are collapsed. * * @defaultValue * ``` * t(() => $localize`:@@SI_APPLICATION_HEADER.TOGGLE_ACTIONS:Toggle actions`) * ``` */ readonly mobileToggleLabel = input( t(() => $localize`:@@SI_APPLICATION_HEADER.TOGGLE_ACTIONS:Toggle actions`) ); /** @internal **/ readonly mobileExpanded = signal(false); /** @internal **/ readonly badgeCount = signal(0); protected readonly id = `__si-header-collapsible-actions-${SiHeaderCollapsibleActionsComponent.idCounter++}`; protected readonly icons = addIcons({ elementOptionsVertical }); private readonly toggle = viewChild.required<ElementRef<HTMLDivElement>>('toggle'); private readonly focusTrap = viewChild.required(CdkTrapFocus); private header = inject(SiApplicationHeaderComponent); private closeMobileSub = this.header.closeMobileMenus.subscribe(() => this.closeMobile()); private inlineChangeSubscription?: Subscription; ngOnDestroy(): void { this.closeMobileSub.unsubscribe(); this.inlineChangeSubscription?.unsubscribe(); } protected toggleMobileExpanded(): void { Iif (this.mobileExpanded()) { this.closeMobile(); } else { this.openMobile(); } } protected escapePressed(): void { this.closeMobile(); this.toggle().nativeElement.focus(); } private openMobile(): void { if (!this.mobileExpanded()) { this.header.closeMobileMenus.next(); this.header.dropdownOpened(); this.mobileExpanded.set(true); this.inlineChangeSubscription = this.header.inlineDropdown .pipe(skip(1), takeUntil(this.header.closeMobileMenus)) .subscribe(() => this.header.closeMobileMenus.next()); this.focusTrap().focusTrap.focusFirstTabbableElementWhenReady(); } } private closeMobile(): void { if (this.mobileExpanded()) { this.header.dropdownClosed(); this.mobileExpanded.set(false); this.toggle().nativeElement.focus(); } } } |