UNPKG

igniteui-angular

Version:

Ignite UI for Angular is a dependency-free Angular toolkit for building modern web apps

911 lines (896 loc) 45.2 kB
import * as i6 from 'igniteui-angular/input-group'; import { IgxPrefixDirective, IgxSuffixDirective } from 'igniteui-angular/input-group'; import * as i0 from '@angular/core'; import { inject, EventEmitter, booleanAttribute, Input, Output, ViewChild, ContentChild, Directive, ElementRef, HostBinding, Component, HostListener, ContentChildren, NgZone, NgModule } from '@angular/core'; import { CarouselAnimationDirection, IgxCarouselComponentBase } from 'igniteui-angular/carousel'; import { PlatformUtil, ɵIgxDirectionality as _IgxDirectionality, getResizeObserver } from 'igniteui-angular/core'; import { NgClass, NgTemplateOutlet } from '@angular/common'; import { IgxRippleDirective, IgxIconButtonDirective } from 'igniteui-angular/directives'; import { IgxIconComponent } from 'igniteui-angular/icon'; /** @hidden */ class IgxTabsBase { } /** @hidden */ class IgxTabItemBase { } /** @hidden */ class IgxTabHeaderBase { } /** @hidden */ class IgxTabContentBase { } class IgxTabItemDirective { constructor() { /** @hidden */ this.tabs = inject(IgxTabsBase); /** * Output to enable support for two-way binding on [(selected)] */ this.selectedChange = new EventEmitter(); /** * Disables the item. */ this.disabled = false; /** @hidden */ this.direction = CarouselAnimationDirection.NONE; this._selected = false; } /** * Gets/Sets whether an item is selected. */ get selected() { return this._selected; } set selected(value) { if (this._selected !== value) { this._selected = value; this.tabs.selectTab(this, this._selected); this.selectedChange.emit(this._selected); } } static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.2", ngImport: i0, type: IgxTabItemDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); } static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "16.1.0", version: "21.0.2", type: IgxTabItemDirective, isStandalone: true, inputs: { disabled: ["disabled", "disabled", booleanAttribute], selected: ["selected", "selected", booleanAttribute] }, outputs: { selectedChange: "selectedChange" }, queries: [{ propertyName: "headerComponent", first: true, predicate: IgxTabHeaderBase, descendants: true }, { propertyName: "panelComponent", first: true, predicate: IgxTabContentBase, descendants: true }], viewQueries: [{ propertyName: "headerTemplate", first: true, predicate: ["headerTemplate"], descendants: true, static: true }, { propertyName: "panelTemplate", first: true, predicate: ["panelTemplate"], descendants: true, static: true }], ngImport: i0 }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.2", ngImport: i0, type: IgxTabItemDirective, decorators: [{ type: Directive }], propDecorators: { headerComponent: [{ type: ContentChild, args: [IgxTabHeaderBase] }], panelComponent: [{ type: ContentChild, args: [IgxTabContentBase] }], headerTemplate: [{ type: ViewChild, args: ['headerTemplate', { static: true }] }], panelTemplate: [{ type: ViewChild, args: ['panelTemplate', { static: true }] }], selectedChange: [{ type: Output }], disabled: [{ type: Input, args: [{ transform: booleanAttribute }] }], selected: [{ type: Input, args: [{ transform: booleanAttribute }] }] } }); class IgxTabContentDirective { constructor() { /** @hidden */ this.tab = inject(IgxTabItemDirective); /** @hidden */ this.elementRef = inject((ElementRef)); /** @hidden */ this.role = 'tabpanel'; } /** @hidden */ get tabIndex() { return this.tab.selected ? 0 : -1; } /** @hidden */ get zIndex() { return this.tab.selected ? 'auto' : -1; } /** @hidden */ get nativeElement() { return this.elementRef.nativeElement; } static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.2", ngImport: i0, type: IgxTabContentDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); } static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "21.0.2", type: IgxTabContentDirective, isStandalone: true, host: { properties: { "attr.role": "this.role", "attr.tabindex": "this.tabIndex", "style.z-index": "this.zIndex" } }, ngImport: i0 }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.2", ngImport: i0, type: IgxTabContentDirective, decorators: [{ type: Directive }], propDecorators: { role: [{ type: HostBinding, args: ['attr.role'] }], tabIndex: [{ type: HostBinding, args: ['attr.tabindex'] }], zIndex: [{ type: HostBinding, args: ['style.z-index'] }] } }); class IgxTabContentComponent extends IgxTabContentDirective { constructor() { super(...arguments); /** @hidden */ this.cssClass = true; } static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.2", ngImport: i0, type: IgxTabContentComponent, deps: null, target: i0.ɵɵFactoryTarget.Component }); } static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.2", type: IgxTabContentComponent, isStandalone: true, selector: "igx-tab-content", host: { properties: { "class.igx-tabs__panel": "this.cssClass" } }, providers: [{ provide: IgxTabContentBase, useExisting: IgxTabContentComponent }], usesInheritance: true, ngImport: i0, template: "@if (tab.selected || tab.previous) {\n <ng-content></ng-content>\n}\n" }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.2", ngImport: i0, type: IgxTabContentComponent, decorators: [{ type: Component, args: [{ selector: 'igx-tab-content', providers: [{ provide: IgxTabContentBase, useExisting: IgxTabContentComponent }], imports: [], template: "@if (tab.selected || tab.previous) {\n <ng-content></ng-content>\n}\n" }] }], propDecorators: { cssClass: [{ type: HostBinding, args: ['class.igx-tabs__panel'] }] } }); class IgxTabHeaderDirective { constructor() { /** @hidden */ this.tabs = inject(IgxTabsBase); /** @hidden */ this.tab = inject(IgxTabItemDirective); /** @hidden */ this.elementRef = inject((ElementRef)); /** @hidden */ this.platform = inject(PlatformUtil); /** @hidden */ this.role = 'tab'; } /** @hidden */ get tabIndex() { return this.tab.selected ? 0 : -1; } /** @hidden */ get ariaSelected() { return this.tab.selected; } /** @hidden */ get ariaDisabled() { return this.tab.disabled; } /** @hidden */ onClick() { if (this.tab.panelComponent) { this.tabs.selectTab(this.tab, true); } } /** @hidden */ get nativeElement() { return this.elementRef.nativeElement; } static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.2", ngImport: i0, type: IgxTabHeaderDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); } static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "21.0.2", type: IgxTabHeaderDirective, isStandalone: true, host: { listeners: { "click": "onClick()" }, properties: { "attr.role": "this.role", "attr.tabindex": "this.tabIndex", "attr.aria-selected": "this.ariaSelected", "attr.aria-disabled": "this.ariaDisabled" } }, ngImport: i0 }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.2", ngImport: i0, type: IgxTabHeaderDirective, decorators: [{ type: Directive }], propDecorators: { role: [{ type: HostBinding, args: ['attr.role'] }], tabIndex: [{ type: HostBinding, args: ['attr.tabindex'] }], ariaSelected: [{ type: HostBinding, args: ['attr.aria-selected'] }], ariaDisabled: [{ type: HostBinding, args: ['attr.aria-disabled'] }], onClick: [{ type: HostListener, args: ['click'] }] } }); class IgxTabsDirective extends IgxCarouselComponentBase { constructor() { super(...arguments); /** @hidden */ this.dir = inject(_IgxDirectionality); /** * Enables/disables the transition animation of the contents. */ this.disableAnimation = false; /** * Output to enable support for two-way binding on [(selectedIndex)] */ this.selectedIndexChange = new EventEmitter(); /** * Emitted when the selected index is about to change. */ this.selectedIndexChanging = new EventEmitter(); /** * Emitted when the selected item is changed. */ this.selectedItemChange = new EventEmitter(); this._selectedIndex = -1; } /** * Gets/Sets the index of the selected item. * Default value is 0 if contents are defined otherwise defaults to -1. */ get selectedIndex() { return this._selectedIndex; } set selectedIndex(value) { if (this._selectedIndex !== value) { let newIndex = value; const oldIndex = this._selectedIndex; const args = { owner: this, cancel: false, oldIndex, newIndex }; this.selectedIndexChanging.emit(args); if (!args.cancel) { newIndex = args.newIndex; this._selectedIndex = newIndex; this.selectedIndexChange.emit(this._selectedIndex); } this.updateSelectedTabs(oldIndex); } } /** * Gets the selected item. */ get selectedItem() { return this.items && this.selectedIndex >= 0 && this.selectedIndex < this.items.length ? this.items.get(this.selectedIndex) : null; } /** @hidden */ ngAfterViewInit() { if (this._selectedIndex === -1) { const hasSelectedTab = this.items.some((tab, i) => { if (tab.selected) { this._selectedIndex = i; } return tab.selected; }); if (!hasSelectedTab && this.hasPanels) { this._selectedIndex = 0; } } // Use promise to avoid expression changed after check error Promise.resolve().then(() => { this.updateSelectedTabs(null, false); }); this._itemChanges$ = this.items.changes.subscribe(() => { this.onItemChanges(); }); this.setAttributes(); } /** @hidden */ ngOnDestroy() { super.ngOnDestroy(); if (this._itemChanges$) { this._itemChanges$.unsubscribe(); } } /** @hidden */ selectTab(tab, selected) { if (!this.items) { return; } const tabs = this.items.toArray(); if (selected) { const index = tabs.indexOf(tab); if (index > -1) { this.selectedIndex = index; } } else { if (tabs.every(t => !t.selected)) { this.selectedIndex = -1; } } } /** @hidden */ getPreviousElement() { return this.previousItem.panelComponent.nativeElement; } /** @hidden */ getCurrentElement() { return this.currentItem.panelComponent.nativeElement; } /** @hidden */ scrollTabHeaderIntoView() { } /** @hidden */ onItemChanges() { this.setAttributes(); // Check if there is selected tab let selectedIndex = -1; this.items.some((tab, i) => { if (tab.selected) { selectedIndex = i; } return tab.selected; }); if (selectedIndex >= 0) { // Set the selected index to the tab that has selected=true Promise.resolve().then(() => { this.selectedIndex = selectedIndex; }); } else { if (this.selectedIndex >= 0 && this.selectedIndex < this.items.length) { // Select the tab on the same index the previous selected tab was Promise.resolve().then(() => { this.updateSelectedTabs(null); }); } else if (this.selectedIndex >= this.items.length) { // Select the last tab Promise.resolve().then(() => { this.selectedIndex = this.items.length - 1; }); } } } setAttributes() { this.items.forEach(item => { if (item.panelComponent && !item.headerComponent.nativeElement.getAttribute('id')) { const id = this.getNextTabId(); const tabHeaderId = `${this.componentName}-header-${id}`; const tabPanelId = `${this.componentName}-content-${id}`; this.setHeaderAttribute(item, 'id', tabHeaderId); this.setHeaderAttribute(item, 'aria-controls', tabPanelId); this.setPanelAttribute(item, 'id', tabPanelId); this.setPanelAttribute(item, 'aria-labelledby', tabHeaderId); } }); } setHeaderAttribute(item, attrName, value) { item.headerComponent.nativeElement.setAttribute(attrName, value); } setPanelAttribute(item, attrName, value) { item.panelComponent.nativeElement.setAttribute(attrName, value); } get hasPanels() { return this.panels && this.panels.length; } updateSelectedTabs(oldSelectedIndex, raiseEvent = true) { if (!this.items) { return; } let newTab; const oldTab = this.currentItem; // First select the new tab if (this._selectedIndex >= 0 && this._selectedIndex < this.items.length) { newTab = this.items.get(this._selectedIndex); newTab.selected = true; } // Then unselect the other tabs this.items.forEach((tab, i) => { if (i !== this._selectedIndex) { tab.selected = false; } }); if (this._selectedIndex !== oldSelectedIndex) { this.scrollTabHeaderIntoView(); this.triggerPanelAnimations(oldSelectedIndex); if (raiseEvent && newTab !== oldTab) { this.selectedItemChange.emit({ owner: this, newItem: newTab, oldItem: oldTab }); } } } triggerPanelAnimations(oldSelectedIndex) { const item = this.items.get(this._selectedIndex); if (item && !this.disableAnimation && this.hasPanels && this.currentItem && !this.currentItem.selected) { item.direction = (!this.dir.rtl && this._selectedIndex > oldSelectedIndex) || (this.dir.rtl && this._selectedIndex < oldSelectedIndex) ? CarouselAnimationDirection.NEXT : CarouselAnimationDirection.PREV; if (this.previousItem && this.previousItem.previous) { this.previousItem.previous = false; } this.currentItem.direction = item.direction; this.previousItem = this.currentItem; this.currentItem = item; this.triggerAnimations(); } else { this.currentItem = item; } } static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.2", ngImport: i0, type: IgxTabsDirective, deps: null, target: i0.ɵɵFactoryTarget.Directive }); } static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "16.1.0", version: "21.0.2", type: IgxTabsDirective, isStandalone: true, inputs: { selectedIndex: "selectedIndex", disableAnimation: ["disableAnimation", "disableAnimation", booleanAttribute] }, outputs: { selectedIndexChange: "selectedIndexChange", selectedIndexChanging: "selectedIndexChanging", selectedItemChange: "selectedItemChange" }, queries: [{ propertyName: "items", predicate: IgxTabItemDirective }, { propertyName: "panels", predicate: IgxTabContentBase, descendants: true }], usesInheritance: true, ngImport: i0 }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.2", ngImport: i0, type: IgxTabsDirective, decorators: [{ type: Directive }], propDecorators: { selectedIndex: [{ type: Input }], disableAnimation: [{ type: Input, args: [{ transform: booleanAttribute }] }], selectedIndexChange: [{ type: Output }], selectedIndexChanging: [{ type: Output }], selectedItemChange: [{ type: Output }], items: [{ type: ContentChildren, args: [IgxTabItemDirective] }], panels: [{ type: ContentChildren, args: [IgxTabContentBase, { descendants: true }] }] } }); const IgxTabsAlignment = { start: 'start', end: 'end', center: 'center', justify: 'justify' }; /** @hidden */ let NEXT_TAB_ID = 0; /** * Tabs component is used to organize or switch between similar data sets. * * @igxModule IgxTabsModule * * @igxTheme igx-tabs-theme * * @igxKeywords tabs * * @igxGroup Layouts * * @remarks * The Ignite UI for Angular Tabs component places tabs at the top and allows for scrolling when there are multiple tab items on the screen. * * @example * ```html * <igx-tabs> * <igx-tab-item> * <igx-tab-header> * <igx-icon igxTabHeaderIcon>folder</igx-icon> * <span igxTabHeaderLabel>Tab 1</span> * </igx-tab-header> * <igx-tab-content> * Content 1 * </igx-tab-content> * </igx-tab-item> * ... * </igx-tabs> * ``` */ class IgxTabsComponent extends IgxTabsDirective { constructor() { super(...arguments); this.ngZone = inject(NgZone); this.platform = inject(PlatformUtil); /** * Determines the tab activation. * When set to auto, the tab is instantly selected while navigating with the Left/Right Arrows, Home or End keys and the corresponding panel is displayed. * When set to manual, the tab is only focused. The selection happens after pressing Space or Enter. * Defaults is auto. */ this.activation = 'auto'; /** @hidden */ this.defaultClass = true; /** @hidden */ this.offset = 0; /** @hidden */ this.componentName = 'igx-tabs'; this._tabAlignment = 'start'; } /** * Gets/Sets the tab alignment. Defaults to `start`. */ get tabAlignment() { return this._tabAlignment; } set tabAlignment(value) { this._tabAlignment = value; requestAnimationFrame(() => { this.updateScrollButtons(); this.realignSelectedIndicator(); }); } /** @hidden @internal */ ngAfterViewInit() { super.ngAfterViewInit(); this.ngZone.runOutsideAngular(() => { if (this.platform.isBrowser) { this._resizeObserver = new (getResizeObserver())(() => { this.updateScrollButtons(); this.realignSelectedIndicator(); }); this._resizeObserver.observe(this.headerContainer.nativeElement); this._resizeObserver.observe(this.viewPort.nativeElement); } }); } /** @hidden @internal */ ngOnDestroy() { super.ngOnDestroy(); this.ngZone.runOutsideAngular(() => { this._resizeObserver?.disconnect(); }); } /** @hidden */ scrollPrev() { this.scroll(false); } /** @hidden */ scrollNext() { this.scroll(true); } /** @hidden */ realignSelectedIndicator() { if (this.selectedIndex >= 0 && this.selectedIndex < this.items.length) { const header = this.items.get(this.selectedIndex).headerComponent.nativeElement; this.alignSelectedIndicator(header, 0); } } /** @hidden */ resolveHeaderScrollClasses() { return { 'igx-tabs__header-scroll--start': this.tabAlignment === 'start', 'igx-tabs__header-scroll--end': this.tabAlignment === 'end', 'igx-tabs__header-scroll--center': this.tabAlignment === 'center', 'igx-tabs__header-scroll--justify': this.tabAlignment === 'justify', }; } /** @hidden */ scrollTabHeaderIntoView() { if (this.selectedIndex >= 0) { const tabItems = this.items.toArray(); const tabHeaderNativeElement = tabItems[this.selectedIndex].headerComponent.nativeElement; // Scroll left if there is need if (this.getElementOffset(tabHeaderNativeElement) < this.offset) { this.scrollElement(tabHeaderNativeElement, false); } // Scroll right if there is need const viewPortOffsetWidth = this.viewPort.nativeElement.offsetWidth; const delta = (this.getElementOffset(tabHeaderNativeElement) + tabHeaderNativeElement.offsetWidth) - (viewPortOffsetWidth + this.offset); // Fix for IE 11, a difference is accumulated from the widths calculations if (delta > 1) { this.scrollElement(tabHeaderNativeElement, true); } this.alignSelectedIndicator(tabHeaderNativeElement); } else { this.hideSelectedIndicator(); } } /** @hidden */ getNextTabId() { return NEXT_TAB_ID++; } /** @hidden */ onItemChanges() { super.onItemChanges(); Promise.resolve().then(() => { this.updateScrollButtons(); }); } alignSelectedIndicator(element, duration = 0.3) { if (this.selectedIndicator) { this.selectedIndicator.nativeElement.style.visibility = 'visible'; this.selectedIndicator.nativeElement.style.transitionDuration = duration > 0 ? `${duration}s` : 'initial'; this.selectedIndicator.nativeElement.style.width = `${element.offsetWidth}px`; this.selectedIndicator.nativeElement.style.transform = `translate(${element.offsetLeft}px)`; } } hideSelectedIndicator() { if (this.selectedIndicator) { this.selectedIndicator.nativeElement.style.visibility = 'hidden'; } } scroll(scrollNext) { const tabsArray = this.items.toArray(); for (let index = 0; index < tabsArray.length; index++) { const tab = tabsArray[index]; const element = tab.headerComponent.nativeElement; if (scrollNext) { if (element.offsetWidth + this.getElementOffset(element) > this.viewPort.nativeElement.offsetWidth + this.offset) { this.scrollElement(element, scrollNext); break; } } else { if (this.getElementOffset(element) >= this.offset) { this.scrollElement(tabsArray[index - 1].headerComponent.nativeElement, scrollNext); break; } } } } scrollElement(element, scrollNext) { const viewPortWidth = this.viewPort.nativeElement.offsetWidth; this.offset = (scrollNext) ? element.offsetWidth + this.getElementOffset(element) - viewPortWidth : this.getElementOffset(element); this.viewPort.nativeElement.scrollLeft = this.getOffset(this.offset); this.updateScrollButtons(); } updateScrollButtons() { const itemsContainerWidth = this.getTabItemsContainerWidth(); const scrollPrevButtonStyle = this.resolveLeftScrollButtonStyle(itemsContainerWidth); this.setScrollButtonStyle(this.scrollPrevButton.nativeElement, scrollPrevButtonStyle); const scrollNextButtonStyle = this.resolveRightScrollButtonStyle(itemsContainerWidth); this.setScrollButtonStyle(this.scrollNextButton.nativeElement, scrollNextButtonStyle); } setScrollButtonStyle(button, buttonStyle) { if (buttonStyle === "enabled" /* TabScrollButtonStyle.Enabled */) { button.disabled = false; button.style.display = ''; } else if (buttonStyle === "disabled" /* TabScrollButtonStyle.Disabled */) { button.disabled = true; button.style.display = ''; } else if (buttonStyle === "not_displayed" /* TabScrollButtonStyle.NotDisplayed */) { button.style.display = 'none'; } } resolveLeftScrollButtonStyle(itemsContainerWidth) { const headerContainerWidth = this.headerContainer.nativeElement.offsetWidth; const offset = this.offset; if (offset === 0) { // Fix for IE 11, a difference is accumulated from the widths calculations. if (itemsContainerWidth - headerContainerWidth <= 1) { return "not_displayed" /* TabScrollButtonStyle.NotDisplayed */; } return "disabled" /* TabScrollButtonStyle.Disabled */; } else { return "enabled" /* TabScrollButtonStyle.Enabled */; } } resolveRightScrollButtonStyle(itemsContainerWidth) { const viewPortWidth = this.viewPort.nativeElement.offsetWidth; const headerContainerWidth = this.headerContainer.nativeElement.offsetWidth; const offset = this.offset; const total = offset + viewPortWidth; // Fix for IE 11, a difference is accumulated from the widths calculations. if (itemsContainerWidth - headerContainerWidth <= 1 && offset === 0) { return "not_displayed" /* TabScrollButtonStyle.NotDisplayed */; } if (itemsContainerWidth > total) { return "enabled" /* TabScrollButtonStyle.Enabled */; } else { return "disabled" /* TabScrollButtonStyle.Disabled */; } } getTabItemsContainerWidth() { // We use this hacky way to get the width of the itemsContainer, // because there is inconsistency in IE we cannot use offsetWidth or scrollOffset. const itemsContainerChildrenCount = this.itemsContainer.nativeElement.children.length; let itemsContainerWidth = 0; if (itemsContainerChildrenCount > 1) { const lastTab = this.itemsContainer.nativeElement.children[itemsContainerChildrenCount - 1]; itemsContainerWidth = this.getElementOffset(lastTab) + lastTab.offsetWidth; } return itemsContainerWidth; } getOffset(offset) { return this.dir.rtl ? -offset : offset; } getElementOffset(element) { return this.dir.rtl ? this.itemsWrapper.nativeElement.offsetWidth - element.offsetLeft - element.offsetWidth : element.offsetLeft; } static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.2", ngImport: i0, type: IgxTabsComponent, deps: null, target: i0.ɵɵFactoryTarget.Component }); } static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.2", type: IgxTabsComponent, isStandalone: true, selector: "igx-tabs", inputs: { tabAlignment: "tabAlignment", activation: "activation" }, host: { properties: { "class.igx-tabs": "this.defaultClass" } }, providers: [{ provide: IgxTabsBase, useExisting: IgxTabsComponent }], viewQueries: [{ propertyName: "headerContainer", first: true, predicate: ["headerContainer"], descendants: true, static: true }, { propertyName: "viewPort", first: true, predicate: ["viewPort"], descendants: true, static: true }, { propertyName: "itemsWrapper", first: true, predicate: ["itemsWrapper"], descendants: true, static: true }, { propertyName: "itemsContainer", first: true, predicate: ["itemsContainer"], descendants: true, static: true }, { propertyName: "selectedIndicator", first: true, predicate: ["selectedIndicator"], descendants: true }, { propertyName: "scrollPrevButton", first: true, predicate: ["scrollPrevButton"], descendants: true }, { propertyName: "scrollNextButton", first: true, predicate: ["scrollNextButton"], descendants: true }], usesInheritance: true, ngImport: i0, template: "<div #headerContainer class=\"igx-tabs__header\">\n <button #scrollPrevButton type=\"button\" igxIconButton=\"flat\" igxRipple tabindex=\"-1\" class=\"igx-tabs__header-button\" (click)=\"scrollPrev()\">\n <igx-icon family=\"default\" name=\"prev\"></igx-icon>\n </button>\n <div #viewPort class=\"igx-tabs__header-content\">\n <div #itemsWrapper class=\"igx-tabs__header-wrapper\" role=\"tablist\">\n <div #itemsContainer class=\"igx-tabs__header-scroll\" [ngClass]=\"resolveHeaderScrollClasses()\">\n @for (tab of items; track tab; let i = $index) {\n <ng-container *ngTemplateOutlet=\"tab.headerTemplate\"></ng-container>\n }\n </div>\n @if (items.length > 0) {\n <div #selectedIndicator class=\"igx-tabs__header-active-indicator\">\n </div>\n }\n </div>\n </div>\n <button #scrollNextButton type=\"button\" igxIconButton=\"flat\" igxRipple tabindex=\"-1\" class=\"igx-tabs__header-button\" (click)=\"scrollNext()\">\n <igx-icon family=\"default\" name=\"next\"></igx-icon>\n </button>\n</div>\n<div class=\"igx-tabs__panels\">\n @for (tab of items; track tab; let i = $index) {\n <ng-container *ngTemplateOutlet=\"tab.panelTemplate\"></ng-container>\n }\n</div>\n", dependencies: [{ kind: "directive", type: IgxRippleDirective, selector: "[igxRipple]", inputs: ["igxRippleTarget", "igxRipple", "igxRippleDuration", "igxRippleCentered", "igxRippleDisabled"] }, { kind: "component", type: IgxIconComponent, selector: "igx-icon", inputs: ["ariaHidden", "family", "name", "active"] }, { kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "directive", type: IgxIconButtonDirective, selector: "[igxIconButton]", inputs: ["igxIconButton"] }] }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.2", ngImport: i0, type: IgxTabsComponent, decorators: [{ type: Component, args: [{ selector: 'igx-tabs', providers: [{ provide: IgxTabsBase, useExisting: IgxTabsComponent }], imports: [IgxRippleDirective, IgxIconComponent, NgClass, NgTemplateOutlet, IgxIconButtonDirective], template: "<div #headerContainer class=\"igx-tabs__header\">\n <button #scrollPrevButton type=\"button\" igxIconButton=\"flat\" igxRipple tabindex=\"-1\" class=\"igx-tabs__header-button\" (click)=\"scrollPrev()\">\n <igx-icon family=\"default\" name=\"prev\"></igx-icon>\n </button>\n <div #viewPort class=\"igx-tabs__header-content\">\n <div #itemsWrapper class=\"igx-tabs__header-wrapper\" role=\"tablist\">\n <div #itemsContainer class=\"igx-tabs__header-scroll\" [ngClass]=\"resolveHeaderScrollClasses()\">\n @for (tab of items; track tab; let i = $index) {\n <ng-container *ngTemplateOutlet=\"tab.headerTemplate\"></ng-container>\n }\n </div>\n @if (items.length > 0) {\n <div #selectedIndicator class=\"igx-tabs__header-active-indicator\">\n </div>\n }\n </div>\n </div>\n <button #scrollNextButton type=\"button\" igxIconButton=\"flat\" igxRipple tabindex=\"-1\" class=\"igx-tabs__header-button\" (click)=\"scrollNext()\">\n <igx-icon family=\"default\" name=\"next\"></igx-icon>\n </button>\n</div>\n<div class=\"igx-tabs__panels\">\n @for (tab of items; track tab; let i = $index) {\n <ng-container *ngTemplateOutlet=\"tab.panelTemplate\"></ng-container>\n }\n</div>\n" }] }], propDecorators: { tabAlignment: [{ type: Input }], activation: [{ type: Input }], headerContainer: [{ type: ViewChild, args: ['headerContainer', { static: true }] }], viewPort: [{ type: ViewChild, args: ['viewPort', { static: true }] }], itemsWrapper: [{ type: ViewChild, args: ['itemsWrapper', { static: true }] }], itemsContainer: [{ type: ViewChild, args: ['itemsContainer', { static: true }] }], selectedIndicator: [{ type: ViewChild, args: ['selectedIndicator'] }], scrollPrevButton: [{ type: ViewChild, args: ['scrollPrevButton'] }], scrollNextButton: [{ type: ViewChild, args: ['scrollNextButton'] }], defaultClass: [{ type: HostBinding, args: ['class.igx-tabs'] }] } }); class IgxTabHeaderComponent extends IgxTabHeaderDirective { constructor() { super(...arguments); this.tabs = inject(IgxTabsComponent); this.ngZone = inject(NgZone); this.dir = inject(_IgxDirectionality); /** @hidden @internal */ this.cssClass = true; } /** @hidden @internal */ get provideCssClassSelected() { return this.tab.selected; } /** @hidden @internal */ get provideCssClassDisabled() { return this.tab.disabled; } /** @hidden @internal */ keyDown(event) { let unsupportedKey = false; const itemsArray = this.tabs.items.toArray(); const previousIndex = itemsArray.indexOf(this.tab); let newIndex = previousIndex; const hasDisabledItems = itemsArray.some((item) => item.disabled); switch (event.key) { case this.platform.KEYMAP.ARROW_RIGHT: newIndex = this.getNewSelectionIndex(newIndex, itemsArray, event.key, hasDisabledItems); break; case this.platform.KEYMAP.ARROW_LEFT: newIndex = this.getNewSelectionIndex(newIndex, itemsArray, event.key, hasDisabledItems); break; case this.platform.KEYMAP.HOME: event.preventDefault(); newIndex = 0; while (itemsArray[newIndex].disabled && newIndex < itemsArray.length) { newIndex = newIndex === itemsArray.length - 1 ? 0 : newIndex + 1; } break; case this.platform.KEYMAP.END: event.preventDefault(); newIndex = itemsArray.length - 1; while (hasDisabledItems && itemsArray[newIndex].disabled && newIndex > 0) { newIndex = newIndex === 0 ? itemsArray.length - 1 : newIndex - 1; } break; case this.platform.KEYMAP.ENTER: case this.platform.KEYMAP.SPACE: event.preventDefault(); if (this.tabs.activation === 'manual') { this.nativeElement.click(); } unsupportedKey = true; break; default: unsupportedKey = true; break; } if (!unsupportedKey) { itemsArray[newIndex].headerComponent.nativeElement.focus({ preventScroll: true }); if (this.tabs.activation === 'auto') { this.tabs.selectedIndex = newIndex; } } } /** @hidden @internal */ ngAfterViewInit() { this.ngZone.runOutsideAngular(() => { if (this.platform.isBrowser) { this._resizeObserver = new (getResizeObserver())(() => { this.tabs.realignSelectedIndicator(); }); this._resizeObserver.observe(this.nativeElement); } }); } /** @hidden @internal */ ngOnDestroy() { this.ngZone.runOutsideAngular(() => { this._resizeObserver?.disconnect(); }); } getNewSelectionIndex(newIndex, itemsArray, key, hasDisabledItems) { if ((key === this.platform.KEYMAP.ARROW_RIGHT && !this.dir.rtl) || (key === this.platform.KEYMAP.ARROW_LEFT && this.dir.rtl)) { newIndex = newIndex === itemsArray.length - 1 ? 0 : newIndex + 1; while (hasDisabledItems && itemsArray[newIndex].disabled && newIndex < itemsArray.length) { newIndex = newIndex === itemsArray.length - 1 ? 0 : newIndex + 1; } } else { newIndex = newIndex === 0 ? itemsArray.length - 1 : newIndex - 1; while (hasDisabledItems && itemsArray[newIndex].disabled && newIndex >= 0) { newIndex = newIndex === 0 ? itemsArray.length - 1 : newIndex - 1; } } return newIndex; } static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.2", ngImport: i0, type: IgxTabHeaderComponent, deps: null, target: i0.ɵɵFactoryTarget.Component }); } static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.0.2", type: IgxTabHeaderComponent, isStandalone: true, selector: "igx-tab-header", host: { listeners: { "keydown": "keyDown($event)" }, properties: { "class.igx-tabs__header-item--selected": "this.provideCssClassSelected", "class.igx-tabs__header-item--disabled": "this.provideCssClassDisabled", "class.igx-tabs__header-item": "this.cssClass" } }, providers: [{ provide: IgxTabHeaderBase, useExisting: IgxTabHeaderComponent }], usesInheritance: true, ngImport: i0, template: "<ng-content select=\"igx-prefix,[igxPrefix]\"></ng-content>\n\n<div class=\"igx-tabs__header-item-inner\">\n <ng-content></ng-content>\n</div>\n\n<ng-content select=\"igx-suffix,[igxSuffix]\"></ng-content>\n" }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.2", ngImport: i0, type: IgxTabHeaderComponent, decorators: [{ type: Component, args: [{ selector: 'igx-tab-header', providers: [{ provide: IgxTabHeaderBase, useExisting: IgxTabHeaderComponent }], standalone: true, template: "<ng-content select=\"igx-prefix,[igxPrefix]\"></ng-content>\n\n<div class=\"igx-tabs__header-item-inner\">\n <ng-content></ng-content>\n</div>\n\n<ng-content select=\"igx-suffix,[igxSuffix]\"></ng-content>\n" }] }], propDecorators: { provideCssClassSelected: [{ type: HostBinding, args: ['class.igx-tabs__header-item--selected'] }], provideCssClassDisabled: [{ type: HostBinding, args: ['class.igx-tabs__header-item--disabled'] }], cssClass: [{ type: HostBinding, args: ['class.igx-tabs__header-item'] }], keyDown: [{ type: HostListener, args: ['keydown', ['$event']] }] } }); class IgxTabItemComponent extends IgxTabItemDirective { static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.2", ngImport: i0, type: IgxTabItemComponent, deps: null, target: i0.ɵɵFactoryTarget.Component }); } static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.0.2", type: IgxTabItemComponent, isStandalone: true, selector: "igx-tab-item", providers: [{ provide: IgxTabItemDirective, useExisting: IgxTabItemComponent }], usesInheritance: true, ngImport: i0, template: "<ng-template #headerTemplate>\n <ng-content select=\"igx-tab-header\"></ng-content>\n</ng-template>\n<ng-template #panelTemplate>\n <ng-content select=\"igx-tab-content\"></ng-content>\n</ng-template>\n" }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.2", ngImport: i0, type: IgxTabItemComponent, decorators: [{ type: Component, args: [{ selector: 'igx-tab-item', providers: [{ provide: IgxTabItemDirective, useExisting: IgxTabItemComponent }], standalone: true, template: "<ng-template #headerTemplate>\n <ng-content select=\"igx-tab-header\"></ng-content>\n</ng-template>\n<ng-template #panelTemplate>\n <ng-content select=\"igx-tab-content\"></ng-content>\n</ng-template>\n" }] }] }); class IgxTabHeaderLabelDirective { static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.2", ngImport: i0, type: IgxTabHeaderLabelDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); } static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "21.0.2", type: IgxTabHeaderLabelDirective, isStandalone: true, selector: "igx-tab-header-label,[igxTabHeaderLabel]", ngImport: i0 }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.2", ngImport: i0, type: IgxTabHeaderLabelDirective, decorators: [{ type: Directive, args: [{ selector: 'igx-tab-header-label,[igxTabHeaderLabel]', standalone: true }] }] }); class IgxTabHeaderIconDirective { static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.2", ngImport: i0, type: IgxTabHeaderIconDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); } static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "21.0.2", type: IgxTabHeaderIconDirective, isStandalone: true, selector: "igx-tab-header-icon,[igxTabHeaderIcon]", ngImport: i0 }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.2", ngImport: i0, type: IgxTabHeaderIconDirective, decorators: [{ type: Directive, args: [{ selector: 'igx-tab-header-icon,[igxTabHeaderIcon]', standalone: true }] }] }); /* NOTE: Tabs directives collection for ease-of-use import in standalone components scenario */ const IGX_TABS_DIRECTIVES = [ IgxTabsComponent, IgxTabItemComponent, IgxTabHeaderComponent, IgxTabContentComponent, IgxTabHeaderLabelDirective, IgxTabHeaderIconDirective, IgxPrefixDirective, IgxSuffixDirective ]; /** * @hidden * IMPORTANT: The following is NgModule exported for backwards-compatibility before standalone components */ class IgxTabsModule { static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.2", ngImport: i0, type: IgxTabsModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); } static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "21.0.2", ngImport: i0, type: IgxTabsModule, imports: [IgxTabsComponent, IgxTabItemComponent, IgxTabHeaderComponent, IgxTabContentComponent, IgxTabHeaderLabelDirective, IgxTabHeaderIconDirective, i6.IgxPrefixDirective, i6.IgxSuffixDirective], exports: [IgxTabsComponent, IgxTabItemComponent, IgxTabHeaderComponent, IgxTabContentComponent, IgxTabHeaderLabelDirective, IgxTabHeaderIconDirective, i6.IgxPrefixDirective, i6.IgxSuffixDirective] }); } static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "21.0.2", ngImport: i0, type: IgxTabsModule, imports: [IgxTabsComponent] }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.2", ngImport: i0, type: IgxTabsModule, decorators: [{ type: NgModule, args: [{ imports: [ ...IGX_TABS_DIRECTIVES ], exports: [ ...IGX_TABS_DIRECTIVES ] }] }] }); /** * Generated bundle index. Do not edit. */ export { IGX_TABS_DIRECTIVES, IgxTabContentBase, IgxTabContentComponent, IgxTabContentDirective, IgxTabHeaderBase, IgxTabHeaderComponent, IgxTabHeaderDirective, IgxTabHeaderIconDirective, IgxTabHeaderLabelDirective, IgxTabItemBase, IgxTabItemComponent, IgxTabItemDirective, IgxTabsAlignment, IgxTabsBase, IgxTabsComponent, IgxTabsDirective, IgxTabsModule }; //# sourceMappingURL=igniteui-angular-tabs.mjs.map