@progress/kendo-angular-layout
Version:
Kendo UI for Angular Layout Package - a collection of components to create professional application layoyts
910 lines (903 loc) • 41.4 kB
JavaScript
/**-----------------------------------------------------------------------------------------
* Copyright © 2025 Progress Software Corporation. All rights reserved.
* Licensed under commercial license. See LICENSE.md in the project root for more information
*-------------------------------------------------------------------------------------------*/
import { Component, ContentChildren, ElementRef, EventEmitter, HostBinding, Input, Output, QueryList, ViewChild, ViewChildren, Renderer2, NgZone, isDevMode } from '@angular/core';
import { animate, state, style, transition, trigger } from '@angular/animations';
import { LocalizationService, L10N_PREFIX } from '@progress/kendo-angular-l10n';
import { validatePackage } from '@progress/kendo-licensing';
import { packageMetadata } from '../package-metadata';
import { hasClass } from './../common/dom-queries';
import { TabStripTabComponent } from './models/tabstrip-tab.component';
import { TabStripService } from './tabstrip.service';
import { ScrollService } from './tabstrip-scroll.service';
import { Subscription } from 'rxjs';
import { isFocusable } from '../common/dom-queries';
import { getTabByIndex, isTablistHorizontal, tabStripHasScrollButtons, mouseScrollEnabled, resetTabFocus, getId } from './util';
import { normalizeScrollableSettings } from './models/scrollable-settings';
import { TabScrollEvent } from './events/tabscroll-event';
import { TabStripScrollableButtonComponent } from './scrollable-button.component';
import { take } from 'rxjs/operators';
import { guid, isDocumentAvailable, shouldShowValidationUI, WatermarkOverlayComponent, ResizeSensorComponent } from '@progress/kendo-angular-common';
import { TabComponent } from './rendering/tab.component';
import { NgIf, NgTemplateOutlet, NgClass, NgFor, NgStyle } from '@angular/common';
import { LocalizedTabStripMessagesDirective } from './localization/localized-messages.directive';
import * as i0 from "@angular/core";
import * as i1 from "@progress/kendo-angular-l10n";
import * as i2 from "./tabstrip.service";
import * as i3 from "./tabstrip-scroll.service";
/**
* Represents the [Kendo UI TabStrip component for Angular]({% slug overview_tabstrip %}).
*/
export class TabStripComponent {
localization;
renderer;
wrapper;
tabstripService;
scrollService;
ngZone;
/**
* Sets the height of the TabStrip.
*/
set height(value) {
this._height = value;
this.renderer.setStyle(this.wrapper.nativeElement, 'height', value);
}
get height() {
return this._height;
}
/**
* Enables the tab animation.
*
* @default true
*/
animate = true;
/**
* Sets the alignment of the tabs.
*
* @default: 'start'
*/
tabAlignment = 'start';
/**
* Sets the position of the tabs. Defaults to `top`.
*
* @default 'top'
*/
tabPosition = 'top';
/**
* When set to `true`, the component renders all tabs and they are persisted in the DOM.
* By default, `keepTabContent` is `false`.
*
* @default false
*/
keepTabContent = false;
/**
* When set to `true`, a close button will be rendered inside each tab.
* By default, `closable` is `false`.
*
* @default false
*/
closable = false;
/**
* Enables the scrolling of the tab list. When set to `true` and the total size of all tabs
* is greater than the size of the TabStrip container, scroll buttons will be rendered on each end of the tab list.
*
* By default, `scrollable` is `false`.
*
* @default false
*/
set scrollable(value) {
this._scrollableSettings = normalizeScrollableSettings(value);
if (this.tablist) {
this.toggleScrollButtons(this.scrollService.tabsOverflow);
if (this.isScrollable && this.mouseScrollEnabled) {
this.attachTablistScrollHandler(this.tablist.nativeElement);
}
}
}
get scrollable() {
return this._scrollableSettings;
}
/**
* Specifies the size of the TabStrip.
* ([see example](slug:api_layout_tabstripcomponent#toc-size).
*
* The possible values are:
* * `small`
* * `medium` (Default)
* * `large`
* * `none`
*/
set size(value) {
switch (value) {
case 'small':
this.renderer.removeClass(this.wrapper.nativeElement, 'k-tabstrip-md');
this.renderer.removeClass(this.wrapper.nativeElement, 'k-tabstrip-lg');
this.renderer.addClass(this.wrapper.nativeElement, 'k-tabstrip-sm');
break;
case 'medium':
this.renderer.removeClass(this.wrapper.nativeElement, 'k-tabstrip-sm');
this.renderer.removeClass(this.wrapper.nativeElement, 'k-tabstrip-lg');
this.renderer.addClass(this.wrapper.nativeElement, 'k-tabstrip-md');
break;
case 'large':
this.renderer.removeClass(this.wrapper.nativeElement, 'k-tabstrip-md');
this.renderer.removeClass(this.wrapper.nativeElement, 'k-tabstrip-sm');
this.renderer.addClass(this.wrapper.nativeElement, 'k-tabstrip-lg');
break;
case 'none':
this.renderer.removeClass(this.wrapper.nativeElement, 'k-tabstrip-md');
this.renderer.removeClass(this.wrapper.nativeElement, 'k-tabstrip-lg');
this.renderer.removeClass(this.wrapper.nativeElement, 'k-tabstrip-sm');
}
this._size = value;
this.ngZone.onStable.pipe(take(1)).subscribe(() => this.onResize());
}
get size() {
return this._size;
}
/**
* Defines the name for an existing font icon in the Kendo UI theme for the close icon.
*/
closeIcon = 'x';
/**
* Allows defining a custom CSS class, or multiple classes separated by spaces, which will be applied to the close button.
*/
closeIconClass;
/**
* Defines an SVGIcon to be rendered for the close icon.
* The input can take either an [existing Kendo SVG icon](slug:svgicon_list) or a custom one.
*/
set closeSVGIcon(icon) {
if (isDevMode() && icon && this.closeIcon && this.closeIcon !== 'x') {
throw new Error('Setting both closeIcon and svgIcon options at the same time is not supported.');
}
this._closeSVGIcon = icon;
}
get closeSVGIcon() {
return this._closeSVGIcon;
}
/**
* Determines whether the content associated with each tab will be rendered.
*
* @default true
*/
showContentArea = true;
/**
* Fires each time the user selects a tab ([see example](slug:events_tabstrip)).
* The event data contains the index of the selected tab and its title.
*/
tabSelect = new EventEmitter();
/**
* Fires each time the user closes a tab.
* The event data contains the index of the closed tab and its instance.
*/
tabClose = new EventEmitter();
/**
* Fires each time the user scrolls the TabStrip list.
* The event is preventable.
*/
tabScroll = new EventEmitter();
hostClasses = true;
get tabsAtTop() {
return this.tabPosition === 'top';
}
get tabsAtRight() {
return this.tabPosition === 'right';
}
get tabsAtBottom() {
return this.tabPosition === 'bottom';
}
get tabsAtLeft() {
return this.tabPosition === 'left';
}
get dir() {
return this.localization.rtl ? 'rtl' : 'ltr';
}
get tabStripScrollable() {
return this._scrollableSettings.enabled;
}
get tabStripScrollableOverlay() {
return this._scrollableSettings.enabled && !this.hasScrollButtons.visible;
}
/**
* A query list of all declared tabs.
*/
tabs = new QueryList();
/**
* @hidden
*/
tablist;
/**
* @hidden
*/
tabHeaderContainers;
/**
* @hidden
*/
prevScrollButton;
/**
* @hidden
*/
nextScrollButton;
/**
* @hidden
*/
localizationChangeSubscription;
/**
* @hidden
*/
showLicenseWatermark = false;
_height;
_scrollableSettings = normalizeScrollableSettings(false);
subscriptions = new Subscription();
subscriptionsArePresent = false;
_closeSVGIcon;
tabStripId = guid();
tabsChangesSub;
activeStateChangeSub;
_size = 'medium';
constructor(localization, renderer, wrapper, tabstripService, scrollService, ngZone) {
this.localization = localization;
this.renderer = renderer;
this.wrapper = wrapper;
this.tabstripService = tabstripService;
this.scrollService = scrollService;
this.ngZone = ngZone;
const isValid = validatePackage(packageMetadata);
this.showLicenseWatermark = shouldShowValidationUI(isValid);
this.tabstripService.owner = this;
this.scrollService.owner = this;
this.subscriptions.add(this.scrollService.scrollButtonActiveStateChange.subscribe((activeButtonSettings) => {
if (this.hasScrollButtons.visible) {
const action = activeButtonSettings.active ? 'remove' : 'add';
this.renderer[`${action}Class`](this[`${activeButtonSettings.buttonType}ScrollButton`].host.nativeElement, 'k-disabled');
}
}));
}
ngAfterViewInit() {
if (!isDocumentAvailable()) {
return;
}
this.ngZone.runOutsideAngular(() => {
if (this.scrollService.tabsOverflow) {
this.toggleScrollButtons(true);
}
else {
this.toggleScrollButtons(false);
}
setTimeout(() => {
this.scrollToSelectedTab();
});
});
this.initDomEvents();
this.tabsChangesSub = this.tabs.changes.subscribe(() => {
this.ngZone.onStable.pipe(take(1)).subscribe(() => {
this.toggleScrollButtons(this.scrollService.tabsOverflow);
this.scrollService.toggleScrollButtonsState();
});
});
this.isScrollable && !this.hasScrollButtons.visible && this.setScrollableOverlayClasses();
}
ngOnChanges(changes) {
if (!isDocumentAvailable()) {
return;
}
const positionChange = changes['tabPosition'];
if (positionChange) {
const tabsAtBottomChanged = positionChange.previousValue === 'bottom' || positionChange.currentValue === 'bottom';
this.ngZone.onStable.pipe(take(1)).subscribe(() => {
if (tabsAtBottomChanged) {
if (this.subscriptionsArePresent) {
this.subscriptions.unsubscribe();
this.subscriptions = new Subscription();
this.subscriptionsArePresent = false;
this.activeStateChangeSub = this.scrollService.scrollButtonActiveStateChange.subscribe((activeButtonSettings) => {
if (this.hasScrollButtons.visible) {
const action = activeButtonSettings.active ? 'remove' : 'add';
this.renderer[`${action}Class`](this[`${activeButtonSettings.buttonType}ScrollButton`].host.nativeElement, 'k-disabled');
}
});
}
this.initDomEvents();
}
this.scrollService.restoreScrollPosition();
});
}
}
ngOnDestroy() {
if (this.subscriptions) {
this.subscriptions.unsubscribe();
}
if (this.tabsChangesSub) {
this.tabsChangesSub.unsubscribe();
}
if (this.activeStateChangeSub) {
this.activeStateChangeSub.unsubscribe();
}
}
/**
* @hidden
*/
get isScrollable() {
return this._scrollableSettings.enabled;
}
/**
* @hidden
*/
get hasScrollButtons() {
return tabStripHasScrollButtons(this._scrollableSettings);
}
/**
* @hidden
*/
get mouseScrollEnabled() {
return mouseScrollEnabled(this._scrollableSettings);
}
/**
* @hidden
*/
get itemsWrapperClass() {
return isTablistHorizontal(this.tabPosition) ? 'k-hstack' : 'k-vstack';
}
/**
* Allows the user to select a tab programmatically.
* @param {number} index - The index of the tab that will be selected.
*/
selectTab(index) {
const tab = getTabByIndex(this.tabs, index);
if (!tab || tab.disabled) {
return;
}
this.tabstripService.selectTab(tab, index);
this.scrollToSelectedTab();
}
/**
* @hidden
*/
getTabId(idx) {
return getId('k-tabstrip-tab', this.tabStripId, idx);
}
/**
* @hidden
*/
getTabPanelId(idx) {
return getId('k-tabstrip-tabpanel', this.tabStripId, idx);
}
/**
* @hidden
*/
onTabClick(originalEvent, tabIndex) {
if (isFocusable(originalEvent.target)) {
return;
}
const targetElement = originalEvent.target;
const isTargetCloseButton = hasClass(targetElement, 'k-remove-tab') || hasClass(targetElement.parentElement, 'k-remove-tab');
if (isTargetCloseButton) {
return;
}
const tab = getTabByIndex(this.tabs, tabIndex);
this.tabstripService.onTabSelect(tab, tabIndex);
this.scrollToSelectedTab();
}
/**
* @hidden
*/
onResize() {
if (this.scrollService.tabsOverflow) {
this.toggleScrollButtons(true);
}
else {
this.toggleScrollButtons(false);
}
this.ngZone.runOutsideAngular(() => {
this.scrollService.toggleScrollButtonsState();
});
}
/**
* @hidden
*/
scrollToSelectedTab() {
if (this._scrollableSettings.enabled) {
this.scrollService.scrollToSelectedTab();
}
}
/**
* @hidden
*/
onScrollButtonClick(buttonType) {
this.scrollService.scrollTabs(buttonType);
}
initDomEvents() {
if (!this.wrapper || this.subscriptionsArePresent) {
return;
}
const tablist = this.tablist.nativeElement;
this.ngZone.runOutsideAngular(() => {
this.subscriptions.add(this.renderer.listen(tablist, 'keydown', (ev) => {
this.tabstripService.onKeyDown(ev);
}));
});
this.subscriptions.add(this.renderer.listen(tablist, 'focusout', () => {
resetTabFocus(this.tabs);
}));
if (this.isScrollable && this.mouseScrollEnabled) {
this.attachTablistScrollHandler(tablist);
}
this.subscriptionsArePresent = true;
}
toggleScrollButtons(tabsOverflow) {
this.ngZone.onStable.pipe(take(1)).subscribe(() => {
const scrollButtonsSetting = this._scrollableSettings.scrollButtons;
const scrollButtonsArePresent = this.prevScrollButton && this.nextScrollButton;
const shouldShowButtons = scrollButtonsArePresent && tabsOverflow;
const shouldHideButtons = scrollButtonsArePresent &&
!tabsOverflow &&
scrollButtonsSetting !== 'visible';
const alwaysVisible = scrollButtonsSetting === 'visible';
if (shouldHideButtons) {
this.prevScrollButton.toggle(false);
this.nextScrollButton.toggle(false);
}
else if (shouldShowButtons || alwaysVisible) {
this.prevScrollButton.toggle(true);
this.nextScrollButton.toggle(true);
}
if (scrollButtonsArePresent) {
this.ngZone.runOutsideAngular(() => {
this.scrollService.toggleScrollButtonsState();
});
}
});
}
attachTablistScrollHandler(tablist) {
this.ngZone.runOutsideAngular(() => {
this.subscriptions.add(this.renderer.listen(tablist, 'scroll', (e) => {
const scrollEvent = new TabScrollEvent({
originalEvent: e
});
this.tabScroll.emit(scrollEvent);
const isTabStripScrollEventPrevented = scrollEvent.isDefaultPrevented();
if (isTabStripScrollEventPrevented || !this.scrollService.tabsOverflow) {
return;
}
if (!this.hasScrollButtons.visible) {
this.setScrollableOverlayClasses();
}
this.scrollService.onScroll(e);
}));
});
}
setScrollableOverlayClasses() {
const wrapper = this.wrapper.nativeElement;
const container = this.tablist?.nativeElement;
if (!container) {
return;
}
const scrollOffset = isTablistHorizontal(this.tabPosition) ? container.scrollLeft : container.scrollTop;
if (scrollOffset === 0) {
this.renderer.removeClass(wrapper, 'k-tabstrip-scrollable-end');
this.renderer.addClass(wrapper, 'k-tabstrip-scrollable-start');
}
else if (scrollOffset > 0 && scrollOffset < this.scrollService.tablistOverflowSize) {
this.renderer.removeClass(wrapper, 'k-tabstrip-scrollable-end');
this.renderer.removeClass(wrapper, 'k-tabstrip-scrollable-start');
}
else {
this.renderer.removeClass(wrapper, 'k-tabstrip-scrollable-start');
this.renderer.addClass(wrapper, 'k-tabstrip-scrollable-end');
}
}
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: TabStripComponent, deps: [{ token: i1.LocalizationService }, { token: i0.Renderer2 }, { token: i0.ElementRef }, { token: i2.TabStripService }, { token: i3.ScrollService }, { token: i0.NgZone }], target: i0.ɵɵFactoryTarget.Component });
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.2.12", type: TabStripComponent, isStandalone: true, selector: "kendo-tabstrip", inputs: { height: "height", animate: "animate", tabAlignment: "tabAlignment", tabPosition: "tabPosition", keepTabContent: "keepTabContent", closable: "closable", scrollable: "scrollable", size: "size", closeIcon: "closeIcon", closeIconClass: "closeIconClass", closeSVGIcon: "closeSVGIcon", showContentArea: "showContentArea" }, outputs: { tabSelect: "tabSelect", tabClose: "tabClose", tabScroll: "tabScroll" }, host: { properties: { "class.k-tabstrip": "this.hostClasses", "class.k-tabstrip-md": "this.hostClasses", "class.k-tabstrip-top": "this.tabsAtTop", "class.k-tabstrip-right": "this.tabsAtRight", "class.k-tabstrip-bottom": "this.tabsAtBottom", "class.k-tabstrip-left": "this.tabsAtLeft", "attr.dir": "this.dir", "class.k-tabstrip-scrollable": "this.tabStripScrollable", "class.k-tabstrip-scrollable-overlay": "this.tabStripScrollableOverlay" } }, providers: [
TabStripService,
ScrollService,
LocalizationService,
{
provide: L10N_PREFIX,
useValue: 'kendo.tabstrip'
}
], queries: [{ propertyName: "tabs", predicate: TabStripTabComponent }], viewQueries: [{ propertyName: "tablist", first: true, predicate: ["tablist"], descendants: true }, { propertyName: "prevScrollButton", first: true, predicate: ["prevScrollButton"], descendants: true }, { propertyName: "nextScrollButton", first: true, predicate: ["nextScrollButton"], descendants: true }, { propertyName: "tabHeaderContainers", predicate: ["tabHeaderContainer"], descendants: true, read: ElementRef }], exportAs: ["kendoTabStrip"], usesOnChanges: true, ngImport: i0, template: `
<ng-container kendoTabStripLocalizedMessages
i18n-closeTitle="kendo.tabstrip.closeTitle|The title for the **Close** button in the TabStrip tab."
closeTitle="Close"
i18n-previousTabButton="kendo.tabstrip.previousTabButton|The title for the **Previous Tab** button when the Tabstrip is scrollable."
previousTabButton="Previous Tab"
i18n-nextTabButton="kendo.tabstrip.nextTabButton|The title for the **Next Tab** button when the Tabstrip is scrollable."
nextTabButton="Next Tab"
>
</ng-container>
<ng-container *ngIf="!tabsAtBottom">
<ng-container *ngTemplateOutlet="heading"></ng-container>
<ng-container *ngIf="showContentArea">
<ng-container *ngTemplateOutlet="content"></ng-container>
</ng-container>
</ng-container>
<ng-container *ngIf="tabsAtBottom">
<ng-container *ngIf="showContentArea">
<ng-container *ngTemplateOutlet="content"></ng-container>
</ng-container>
<ng-container *ngTemplateOutlet="heading"></ng-container>
</ng-container>
<ng-template #heading>
<div class="k-tabstrip-items-wrapper" [class.k-tabstrip-items-wrapper-scroll]="mouseScrollEnabled" [ngClass]="itemsWrapperClass">
<span
role="button"
*ngIf="hasScrollButtons.visible && hasScrollButtons.position !== 'end'"
#prevScrollButton
kendoTabStripScrollableButton
[scrollable]="scrollable"
[tabPosition]="tabPosition"
[prev]="true"
[title]="localization.get('previousTabButton')"
(tabScroll)="tabScroll.emit($event)"
class="k-icon-button k-button k-button-flat k-button-flat-base"
[ngClass]="{
'k-button-sm': size === 'small',
'k-button-md': size === 'medium' || !size,
'k-button-lg': size === 'large'
}"
(onClick)="onScrollButtonClick($event)"></span>
<span
role="button"
*ngIf="hasScrollButtons.visible && hasScrollButtons.position === 'start'"
#nextScrollButton
kendoTabStripScrollableButton
[scrollable]="scrollable"
[tabPosition]="tabPosition"
[prev]="false"
[title]="localization.get('nextTabButton')"
(tabScroll)="tabScroll.emit($event)"
class="k-icon-button k-button k-button-flat k-button-flat-base"
[ngClass]="{
'k-button-sm': size === 'small',
'k-button-md': size === 'medium' || !size,
'k-button-lg': size === 'large'
}"
(onClick)="onScrollButtonClick($event)"></span>
<ul role="tablist" #tablist
class="k-reset k-tabstrip-items"
[ngClass]="{
'k-tabstrip-items-start': tabAlignment === 'start',
'k-tabstrip-items-center': tabAlignment === 'center',
'k-tabstrip-items-end': tabAlignment === 'end',
'k-tabstrip-items-stretched': tabAlignment === 'stretched',
'k-tabstrip-items-justify': tabAlignment === 'justify',
'k-tabstrip-items-scroll': mouseScrollEnabled
}"
[attr.aria-orientation]="tabPosition === 'left' || tabPosition === 'right' ? 'vertical' : 'horizontal'"
>
<ng-container *ngFor="let tab of tabs; let i = index;">
<li
#tabHeaderContainer
kendoTabStripTab
[class.k-first]="i === 0"
[class.k-last]="i === tabs.length - 1"
[ngClass]="tab.cssClass"
[ngStyle]="tab.cssStyle"
[tab]="tab"
[index]="i"
role="tab"
[tabStripClosable]="closable"
[tabStripCloseIcon]="closeIcon"
[customTabstripCloseIcon]="closeIconClass"
[closeSVGIcon]="closeSVGIcon"
(tabClose)="tabClose.emit($event)"
(click)="onTabClick($event, i)"
[id]="getTabId(i)"
[attr.aria-controls]="(showContentArea && tab.selected) ? getTabPanelId(i) : undefined"></li>
</ng-container>
</ul>
<span
role="button"
*ngIf="hasScrollButtons.visible && hasScrollButtons.position === 'end'"
#prevScrollButton
kendoTabStripScrollableButton
[scrollable]="scrollable"
[tabPosition]="tabPosition"
[prev]="true"
[title]="localization.get('previousTabButton')"
(tabScroll)="tabScroll.emit($event)"
class="k-icon-button k-button k-button-flat k-button-flat-base"
[ngClass]="{
'k-button-sm': size === 'small',
'k-button-md': size === 'medium' || !size,
'k-button-lg': size === 'large'
}"
(onClick)="onScrollButtonClick($event)"></span>
<span
role="button"
*ngIf="hasScrollButtons.visible && hasScrollButtons.position !== 'start'"
#nextScrollButton
kendoTabStripScrollableButton
[scrollable]="scrollable"
[tabPosition]="tabPosition"
[prev]="false"
[title]="localization.get('nextTabButton')"
(tabScroll)="tabScroll.emit($event)"
class="k-icon-button k-button k-button-flat k-button-flat-base"
[ngClass]="{
'k-button-sm': size === 'small',
'k-button-md': size === 'medium' || !size,
'k-button-lg': size === 'large'
}"
(onClick)="onScrollButtonClick($event)"></span>
</div>
</ng-template>
<ng-template #content>
<ng-template ngFor let-tab [ngForOf]="tabs" let-i="index">
<div
[@state]="tab.selected && animate ? 'active' : 'inactive'"
*ngIf="tab.selected || keepTabContent"
[ngClass]="!this.keepTabContent || tab.selected ? 'k-tabstrip-content k-active' : 'k-tabstrip-content'"
[tabIndex]="0"
role="tabpanel"
[id]="getTabPanelId(i)"
[attr.aria-hidden]="!tab.selected"
[attr.aria-labelledby]="getTabId(i)"
[attr.aria-disabled]="tab.disabled"
>
<ng-template [ngTemplateOutlet]="tab.tabContent?.templateRef">
</ng-template>
</div>
</ng-template>
</ng-template>
<kendo-resize-sensor *ngIf="isScrollable" (resize)="onResize()"></kendo-resize-sensor>
<div kendoWatermarkOverlay *ngIf="showLicenseWatermark"></div>
`, isInline: true, dependencies: [{ kind: "directive", type: LocalizedTabStripMessagesDirective, selector: "[kendoTabStripLocalizedMessages]" }, { kind: "directive", type: NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "component", type: TabStripScrollableButtonComponent, selector: "[kendoTabStripScrollableButton]", inputs: ["prev", "tabPosition", "scrollable"], outputs: ["tabScroll", "onClick"] }, { kind: "directive", type: NgFor, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "component", type: TabComponent, selector: "[kendoTabStripTab]", inputs: ["tab", "index", "tabStripClosable", "tabStripCloseIcon", "customTabstripCloseIcon", "closeSVGIcon"], outputs: ["tabClose"] }, { kind: "directive", type: NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "component", type: ResizeSensorComponent, selector: "kendo-resize-sensor", inputs: ["rateLimit"], outputs: ["resize"] }, { kind: "component", type: WatermarkOverlayComponent, selector: "div[kendoWatermarkOverlay]" }], animations: [
trigger('state', [
state('active', style({ opacity: 1 })),
transition('* => active', [
style({ opacity: 0 }),
animate('400ms ease-in')
])
])
] });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: TabStripComponent, decorators: [{
type: Component,
args: [{
animations: [
trigger('state', [
state('active', style({ opacity: 1 })),
transition('* => active', [
style({ opacity: 0 }),
animate('400ms ease-in')
])
])
],
providers: [
TabStripService,
ScrollService,
LocalizationService,
{
provide: L10N_PREFIX,
useValue: 'kendo.tabstrip'
}
],
exportAs: 'kendoTabStrip',
selector: 'kendo-tabstrip',
template: `
<ng-container kendoTabStripLocalizedMessages
i18n-closeTitle="kendo.tabstrip.closeTitle|The title for the **Close** button in the TabStrip tab."
closeTitle="Close"
i18n-previousTabButton="kendo.tabstrip.previousTabButton|The title for the **Previous Tab** button when the Tabstrip is scrollable."
previousTabButton="Previous Tab"
i18n-nextTabButton="kendo.tabstrip.nextTabButton|The title for the **Next Tab** button when the Tabstrip is scrollable."
nextTabButton="Next Tab"
>
</ng-container>
<ng-container *ngIf="!tabsAtBottom">
<ng-container *ngTemplateOutlet="heading"></ng-container>
<ng-container *ngIf="showContentArea">
<ng-container *ngTemplateOutlet="content"></ng-container>
</ng-container>
</ng-container>
<ng-container *ngIf="tabsAtBottom">
<ng-container *ngIf="showContentArea">
<ng-container *ngTemplateOutlet="content"></ng-container>
</ng-container>
<ng-container *ngTemplateOutlet="heading"></ng-container>
</ng-container>
<ng-template #heading>
<div class="k-tabstrip-items-wrapper" [class.k-tabstrip-items-wrapper-scroll]="mouseScrollEnabled" [ngClass]="itemsWrapperClass">
<span
role="button"
*ngIf="hasScrollButtons.visible && hasScrollButtons.position !== 'end'"
#prevScrollButton
kendoTabStripScrollableButton
[scrollable]="scrollable"
[tabPosition]="tabPosition"
[prev]="true"
[title]="localization.get('previousTabButton')"
(tabScroll)="tabScroll.emit($event)"
class="k-icon-button k-button k-button-flat k-button-flat-base"
[ngClass]="{
'k-button-sm': size === 'small',
'k-button-md': size === 'medium' || !size,
'k-button-lg': size === 'large'
}"
(onClick)="onScrollButtonClick($event)"></span>
<span
role="button"
*ngIf="hasScrollButtons.visible && hasScrollButtons.position === 'start'"
#nextScrollButton
kendoTabStripScrollableButton
[scrollable]="scrollable"
[tabPosition]="tabPosition"
[prev]="false"
[title]="localization.get('nextTabButton')"
(tabScroll)="tabScroll.emit($event)"
class="k-icon-button k-button k-button-flat k-button-flat-base"
[ngClass]="{
'k-button-sm': size === 'small',
'k-button-md': size === 'medium' || !size,
'k-button-lg': size === 'large'
}"
(onClick)="onScrollButtonClick($event)"></span>
<ul role="tablist" #tablist
class="k-reset k-tabstrip-items"
[ngClass]="{
'k-tabstrip-items-start': tabAlignment === 'start',
'k-tabstrip-items-center': tabAlignment === 'center',
'k-tabstrip-items-end': tabAlignment === 'end',
'k-tabstrip-items-stretched': tabAlignment === 'stretched',
'k-tabstrip-items-justify': tabAlignment === 'justify',
'k-tabstrip-items-scroll': mouseScrollEnabled
}"
[attr.aria-orientation]="tabPosition === 'left' || tabPosition === 'right' ? 'vertical' : 'horizontal'"
>
<ng-container *ngFor="let tab of tabs; let i = index;">
<li
#tabHeaderContainer
kendoTabStripTab
[class.k-first]="i === 0"
[class.k-last]="i === tabs.length - 1"
[ngClass]="tab.cssClass"
[ngStyle]="tab.cssStyle"
[tab]="tab"
[index]="i"
role="tab"
[tabStripClosable]="closable"
[tabStripCloseIcon]="closeIcon"
[customTabstripCloseIcon]="closeIconClass"
[closeSVGIcon]="closeSVGIcon"
(tabClose)="tabClose.emit($event)"
(click)="onTabClick($event, i)"
[id]="getTabId(i)"
[attr.aria-controls]="(showContentArea && tab.selected) ? getTabPanelId(i) : undefined"></li>
</ng-container>
</ul>
<span
role="button"
*ngIf="hasScrollButtons.visible && hasScrollButtons.position === 'end'"
#prevScrollButton
kendoTabStripScrollableButton
[scrollable]="scrollable"
[tabPosition]="tabPosition"
[prev]="true"
[title]="localization.get('previousTabButton')"
(tabScroll)="tabScroll.emit($event)"
class="k-icon-button k-button k-button-flat k-button-flat-base"
[ngClass]="{
'k-button-sm': size === 'small',
'k-button-md': size === 'medium' || !size,
'k-button-lg': size === 'large'
}"
(onClick)="onScrollButtonClick($event)"></span>
<span
role="button"
*ngIf="hasScrollButtons.visible && hasScrollButtons.position !== 'start'"
#nextScrollButton
kendoTabStripScrollableButton
[scrollable]="scrollable"
[tabPosition]="tabPosition"
[prev]="false"
[title]="localization.get('nextTabButton')"
(tabScroll)="tabScroll.emit($event)"
class="k-icon-button k-button k-button-flat k-button-flat-base"
[ngClass]="{
'k-button-sm': size === 'small',
'k-button-md': size === 'medium' || !size,
'k-button-lg': size === 'large'
}"
(onClick)="onScrollButtonClick($event)"></span>
</div>
</ng-template>
<ng-template #content>
<ng-template ngFor let-tab [ngForOf]="tabs" let-i="index">
<div
[@state]="tab.selected && animate ? 'active' : 'inactive'"
*ngIf="tab.selected || keepTabContent"
[ngClass]="!this.keepTabContent || tab.selected ? 'k-tabstrip-content k-active' : 'k-tabstrip-content'"
[tabIndex]="0"
role="tabpanel"
[id]="getTabPanelId(i)"
[attr.aria-hidden]="!tab.selected"
[attr.aria-labelledby]="getTabId(i)"
[attr.aria-disabled]="tab.disabled"
>
<ng-template [ngTemplateOutlet]="tab.tabContent?.templateRef">
</ng-template>
</div>
</ng-template>
</ng-template>
<kendo-resize-sensor *ngIf="isScrollable" (resize)="onResize()"></kendo-resize-sensor>
<div kendoWatermarkOverlay *ngIf="showLicenseWatermark"></div>
`,
standalone: true,
imports: [LocalizedTabStripMessagesDirective, NgIf, NgTemplateOutlet, NgClass, TabStripScrollableButtonComponent, NgFor, TabComponent, NgStyle, ResizeSensorComponent, WatermarkOverlayComponent]
}]
}], ctorParameters: function () { return [{ type: i1.LocalizationService }, { type: i0.Renderer2 }, { type: i0.ElementRef }, { type: i2.TabStripService }, { type: i3.ScrollService }, { type: i0.NgZone }]; }, propDecorators: { height: [{
type: Input
}], animate: [{
type: Input
}], tabAlignment: [{
type: Input
}], tabPosition: [{
type: Input
}], keepTabContent: [{
type: Input
}], closable: [{
type: Input
}], scrollable: [{
type: Input
}], size: [{
type: Input
}], closeIcon: [{
type: Input
}], closeIconClass: [{
type: Input
}], closeSVGIcon: [{
type: Input
}], showContentArea: [{
type: Input
}], tabSelect: [{
type: Output
}], tabClose: [{
type: Output
}], tabScroll: [{
type: Output
}], hostClasses: [{
type: HostBinding,
args: ['class.k-tabstrip']
}, {
type: HostBinding,
args: ['class.k-tabstrip-md']
}], tabsAtTop: [{
type: HostBinding,
args: ['class.k-tabstrip-top']
}], tabsAtRight: [{
type: HostBinding,
args: ['class.k-tabstrip-right']
}], tabsAtBottom: [{
type: HostBinding,
args: ['class.k-tabstrip-bottom']
}], tabsAtLeft: [{
type: HostBinding,
args: ['class.k-tabstrip-left']
}], dir: [{
type: HostBinding,
args: ['attr.dir']
}], tabStripScrollable: [{
type: HostBinding,
args: ['class.k-tabstrip-scrollable']
}], tabStripScrollableOverlay: [{
type: HostBinding,
args: ['class.k-tabstrip-scrollable-overlay']
}], tabs: [{
type: ContentChildren,
args: [TabStripTabComponent]
}], tablist: [{
type: ViewChild,
args: ['tablist']
}], tabHeaderContainers: [{
type: ViewChildren,
args: ['tabHeaderContainer', { read: ElementRef }]
}], prevScrollButton: [{
type: ViewChild,
args: ['prevScrollButton']
}], nextScrollButton: [{
type: ViewChild,
args: ['nextScrollButton']
}] } });