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
JavaScript
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