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();
}
}
}
|