UNPKG

@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
/**----------------------------------------------------------------------------------------- * 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'] }] } });