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 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 | 77x 531x 25x 25x 25x 25x 76x 25x 25x 25x 10x 25x 28x 3x 3x 2x 2x 2x 2x 2x 1x 2x 1x 2x 8x 3x | /**
* Copyright (c) Siemens 2016 - 2026
* SPDX-License-Identifier: MIT
*/
import { FocusKeyManager } from '@angular/cdk/a11y';
import { CdkMenuTrigger } from '@angular/cdk/menu';
import { DomPortal } from '@angular/cdk/portal';
import { NgTemplateOutlet } from '@angular/common';
import {
booleanAttribute,
ChangeDetectionStrategy,
Component,
computed,
contentChildren,
effect,
inject,
INJECTOR,
input,
signal,
viewChild
} from '@angular/core';
import { RouterLink } from '@angular/router';
import { elementOptions } from '@siemens/element-icons';
import { isRTL } from '@siemens/element-ng/common';
import { addIcons, SiIconComponent } from '@siemens/element-ng/icon';
import { SiMenuDirective, SiMenuItemComponent } from '@siemens/element-ng/menu';
import { SiResizeObserverModule } from '@siemens/element-ng/resize-observer';
import { SiTabBadgeComponent } from './si-tab-badge.component';
import { SiTabBaseDirective } from './si-tab-base.directive';
import { SiTabLinkComponent } from './si-tab-link.component';
import { SI_TABSET } from './si-tabs-tokens';
/**
* A component to group multiple tabs together.
* Can either be used with {@link SiTabLinkComponent} or {@link SiTabComponent} components.
*/
@Component({
selector: 'si-tabset',
imports: [
SiMenuDirective,
SiMenuItemComponent,
CdkMenuTrigger,
NgTemplateOutlet,
SiResizeObserverModule,
RouterLink,
SiTabBadgeComponent,
SiIconComponent
],
templateUrl: './si-tabset.component.html',
styleUrl: './si-tabset.component.scss',
providers: [
{
provide: SI_TABSET,
useExisting: SiTabsetComponent
}
],
changeDetection: ChangeDetectionStrategy.OnPush
})
export class SiTabsetComponent {
/**
* When set, the overflowing content inside the tab will automatically scroll
* @defaultValue false
**/
readonly contentOverflowAuto = input(false, { transform: booleanAttribute });
protected readonly icons = addIcons({ elementOptions });
private readonly contentNode = viewChild.required('contentNode');
/**
* A `DomPortal` wrapping the tab panel container. Used by {@link SiTabPortalComponent}
* to render the active tab's content at a remote location in the DOM.
*
* @internal
*/
readonly contentPortal = computed(() => new DomPortal(this.contentNode()));
/** @internal */
readonly activeTab = computed(() => this.tabPanels().find(tab => tab.active()));
/** @internal */
readonly tabPanels = contentChildren(SiTabBaseDirective);
/** @internal */
focusKeyManager = new FocusKeyManager(this.tabPanels, inject(INJECTOR))
.withHorizontalOrientation(isRTL() ? 'rtl' : 'ltr')
.withWrap(true);
/** @internal */
protected readonly showMenuButton = signal(false);
protected tabIsLink(tab: unknown): tab is SiTabLinkComponent {
return tab instanceof SiTabLinkComponent;
}
constructor() {
effect(() => {
if (this.showMenuButton() && this.activeTab()) {
// wait for menu button to render on DOM
setTimeout(() => {
this.activeTab()?.scrollTabIntoView();
});
}
});
}
/** @internal */
removedTabByUser(index: number, active?: boolean): void {
// The tab was already removed from the tabPanels list when this function is called.
// We need to:
// - focus another tab if the closed one was focused
// - activate another tab if the closed one was active
// If the closed tab was not focussed, there is no need to restore the focus as it could only be closed by mouse.
for (let i = 0; i < this.tabPanels().length; i++) {
// Get the actual index using modulo to wrap around
const checkIndex = (index + i) % this.tabPanels().length;
const checkTab = this.tabPanels()[checkIndex];
Eif (!checkTab.disabledTab()) {
if (this.focusKeyManager.activeItemIndex === index) {
this.focusKeyManager.setActiveItem(checkIndex);
}
if (active) {
checkTab.selectTab(true);
}
return;
}
}
}
protected resizeContainer(width: number, scrollWidth: number): void {
// 48px is the width of the menu button.
this.showMenuButton.set(scrollWidth > width + (this.showMenuButton() ? 48 : 0));
}
protected keydown(event: KeyboardEvent): void {
this.focusKeyManager.onKeydown(event);
}
}
|