@alyle/ui
Version:
Minimal Design, a set of components for Angular
750 lines (744 loc) • 39.8 kB
JavaScript
import { __decorate } from 'tslib';
import * as i0 from '@angular/core';
import { Directive, EventEmitter, ElementRef, ViewChildren, forwardRef, ContentChildren, Output, Input, ViewChild, ViewEncapsulation, ChangeDetectionStrategy, Component, TemplateRef, ContentChild, HostListener, Optional, NgModule } from '@angular/core';
import * as i1 from '@alyle/ui';
import { st2c, LY_COMMON_STYLES, StyleCollection, mixinStyleUpdater, mixinBg, mixinElevation, mixinShadowColor, mixinColor, mixinRaised, mixinDisabled, mixinOutlined, mixinDisableRipple, XPosition, YPosition, AlignAlias, StyleRenderer, Style, Dir, scrollWithAnimation, LyCommonModule, LyThemeModule, NgTranscludeModule } from '@alyle/ui';
import { LyButton } from '@alyle/ui/button';
import { Subscription, Subject } from 'rxjs';
import * as i5 from '@angular/cdk/portal';
import { TemplatePortal, PortalModule } from '@angular/cdk/portal';
import { switchMapTo, take, takeUntil } from 'rxjs/operators';
import { coerceBooleanProperty } from '@angular/cdk/coercion';
import * as i2 from '@angular/cdk/scrolling';
import * as i3 from '@angular/cdk/platform';
import * as i4 from '@angular/common';
import { CommonModule } from '@angular/common';
import * as i6 from '@angular/cdk/a11y';
class LyTabContent {
constructor(template) {
this.template = template;
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.10", ngImport: i0, type: LyTabContent, deps: [{ token: i0.TemplateRef }], target: i0.ɵɵFactoryTarget.Directive }); }
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "19.2.10", type: LyTabContent, isStandalone: false, selector: "[ly-tab-content]", ngImport: i0 }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.10", ngImport: i0, type: LyTabContent, decorators: [{
type: Directive,
args: [{ selector: '[ly-tab-content]',
standalone: false
}]
}], ctorParameters: () => [{ type: i0.TemplateRef }] });
const DEFAULT_DISABLE_RIPPLE = false;
const STYLE_PRIORITY = -2;
const DEFAULT_BG = 'primary';
const DEFAULT_INDICATOR_COLOR = 'accent';
const DEFAULT_ELEVATION = 4;
const DEFAULT_HEADER_PLACEMENT = 'above';
const STYLES = (theme, ref) => {
const __ = ref.selectorsOf(STYLES);
return {
$name: LyTabs.и,
$priority: STYLE_PRIORITY,
root: () => (_className) => `${_className}{display:flex;}${st2c(((theme.tab
&& theme.tab.root
&& (theme.tab.root instanceof StyleCollection
? theme.tab.root.setTransformer(fn => fn(__)).css
: theme.tab.root(__)))), `${_className}`)}`,
tab: (_className) => `${_className}{position:relative;display:inline-flex;}`,
/** Tab container */
contentContainer: (_className) => `${_className}{display:flex;overflow:hidden;flex-grow:1;width:100%;position:relative;}`,
/** Tab header */
labels: (_className) => `${_className}{display:flex;position:relative;height:100%;}`,
labelsContainer: () => (_className) => `${_className}{overflow:hidden;flex-shrink:0;} (hover: none){${__.scrollable} ${_className}{overflow:auto;}}`,
label: (_className) => `${_className}{-webkit-tap-highlight-color:transparent;-webkit-appearance:none;background-color:transparent;user-select:none;border:0;min-width:72px;padding:0 24px;cursor:pointer;height:48px;display:inline-flex;justify-content:center;align-items:center;position:relative;overflow:hidden;font-family:${theme.typography.fontFamily};font-size:${theme.pxToRem(theme.typography.fontSize)};letter-spacing:0.02857em;color:currentColor;outline:none;width:100%;font-weight:500;opacity:.7;} ${theme.breakpoints['XSmall']}{${_className}{padding:0 12px;}}`,
labelActive: (_className) => `${_className}{opacity:1;}`,
contents: (_className) => `${_className}{display:flex;width:100%;}`,
content: (_className) => `${st2c((LY_COMMON_STYLES.fill), `${_className}`)}${_className}{width:100%;height:100%;position:absolute;overflow:auto;}`,
contentActive: (_className) => `${_className}{position:relative;z-index:1;}`,
contentInner: null,
indicator: (_className) => `${_className}{position:absolute;height:2px;transition:450ms cubic-bezier(.1,1,0.5,1);background:currentColor;}`,
indicatorForServer: (_className) => `${_className}{position:absolute;background:currentColor;}`,
rippleContainer: (_className) => `${st2c((LY_COMMON_STYLES.fill), `${_className}`)}${_className}{overflow:hidden;}`,
scrollable: null,
hiddenContent: () => (_className) => `${_className}{visibility:hidden;}`,
column: null,
row: null
};
};
/** @docs-private */
class LyTabsBase {
constructor(_theme) {
this._theme = _theme;
}
}
/** @docs-private */
const LyTabsMixinBase = mixinStyleUpdater(mixinBg(mixinElevation(mixinShadowColor(LyTabsBase))));
/** @docs-private */
class LyTabLabelBase {
constructor(_theme, _ngZone, _platform) {
this._theme = _theme;
this._ngZone = _ngZone;
this._platform = _platform;
}
}
/** @docs-private */
const LyTabLabelMixinBase = mixinStyleUpdater(mixinBg(mixinColor(mixinRaised(mixinDisabled(mixinOutlined(mixinElevation(mixinShadowColor(mixinDisableRipple(LyTabLabelBase)))))))));
/**
* @dynamic
*/
class LyTabs extends LyTabsMixinBase {
/** @docs-private */
static { this.и = 'LyTabs'; }
/**
* Keep the content.
* By default, when changing a tab, the previous one is created and deleted.
* With this, the content will only be hidden instead of deleting it.
*/
set keepContent(val) {
const newVal = coerceBooleanProperty(val);
this._keepContent = newVal;
}
get keepContent() {
return this._keepContent;
}
/** Animation duration in milliseconds */
set animationDuration(val) {
this._animationDuration = val;
Promise.resolve().then(() => {
this.tabContents.nativeElement.style.transitionDuration = `${val}ms`;
});
}
get animationDuration() {
return this._animationDuration;
}
/**
* Whether the tab group should grow to the size of the active tab.
*/
set dynamicHeight(val) {
const newVal = coerceBooleanProperty(val);
this._dynamicHeight = newVal;
}
get dynamicHeight() {
return this._dynamicHeight;
}
set scrollable(val) {
const newVal = coerceBooleanProperty(val);
if (newVal) {
this.renderer.addClass(this.el.nativeElement, this.classes.scrollable);
}
else if (this._scrollable != null) {
this.renderer.removeClass(this.el.nativeElement, this.classes.scrollable);
}
this._scrollable = newVal;
}
get scrollable() {
return this._scrollable;
}
set headerPlacement(val) {
if (val !== this.headerPlacement) {
this._headerPlacement = val;
this.sRenderer.toggleClass(this.classes.column, val === 'above' || val === 'below');
this.sRenderer.toggleClass(this.classes.row, val === 'before' || val === 'after');
this._headerPlacementClass = this.theme.addStyle(`lyTabs.headerPlacement:${val}`, () => {
let flexDirectionContainer;
let flexDirection = this._getFlexDirection(val);
let position;
let height = null;
let width = null;
let heightServer = null;
let widthServer = null;
switch (val) {
case YPosition.above:
flexDirectionContainer = 'column';
position = YPosition.below;
height = '2px';
widthServer = '100%';
break;
case YPosition.below:
flexDirectionContainer = 'column-reverse';
position = YPosition.above;
height = '2px';
widthServer = '100%';
break;
case XPosition.before:
flexDirectionContainer = 'row';
position = XPosition.after;
width = '2px';
heightServer = '100%';
break;
case XPosition.after:
flexDirectionContainer = 'row-reverse';
position = XPosition.before;
width = '2px';
heightServer = '100%';
break;
default:
throw new Error(`LyTabs: value:${val} do not is valid for \`headerPlacement\``);
}
if (val === YPosition.above || val === YPosition.below) {
flexDirection = 'row';
}
else {
flexDirection = 'column';
}
return {
[`&`]: {
flexDirection: flexDirectionContainer
},
[`& .${this.classes.indicator},& .${this.classes.indicatorForServer}`]: {
[position]: 0,
height,
width
},
[`.${this.classes.indicatorForServer}`]: {
width: widthServer,
height: heightServer
},
[`& .${this.classes.labels},& .${this.classes.contents}`]: { flexDirection },
[`.${this.classes.contents}`]: { flexDirection }
};
}, this.el.nativeElement, this._headerPlacementClass, STYLE_PRIORITY);
}
}
get headerPlacement() {
return this._headerPlacement;
}
set alignTabs(val) {
this._alignTabs = val;
this._alignTabsClass = this.theme.addStyle(`lyAlignTabs: ${val}`, (val === 'stretch' ? {
[`& .${this.classes.labels} .${this.classes.tab}`]: {
flexBasis: 0,
flexGrow: 1
}
} : {
[`& .${this.classes.labels}`]: {
justifyContent: val in AlignAlias ? AlignAlias[val] : val
}
}), this.el.nativeElement, this._alignTabsClass, STYLE_PRIORITY);
}
get alignTabs() {
return this._alignTabs;
}
set textColor(val) {
this._textColor = val;
this._textColorClass = this.theme.addStyle(`lyTabs.textColor:${val}`, (theme) => ({
[`& .${this.classes.labelActive}`]: {
color: theme.colorOf(val)
}
}), this.el.nativeElement, this._textColorClass, STYLE_PRIORITY);
}
get textColor() {
return this._textColor;
}
set selectedIndex(val) {
if (val !== this.selectedIndex) {
this._selectedBeforeIndex = this._selectedIndex;
this._selectedIndex = this._findIndex(val, 'auto');
this._selectedBeforeTab = this._selectedTab;
if (this._isViewInitLoaded) {
this._updateTabs();
}
else {
Promise.resolve(null).then(() => this._updateTabs());
}
this.selectedIndexChange.emit(this._selectedIndex);
this._markForCheck();
}
}
get selectedIndex() {
return this._selectedIndex;
}
constructor(theme, renderer, el, cd, _viewportRuler, sRenderer, _platform, _ngZone) {
super(theme);
this.theme = theme;
this.renderer = renderer;
this.el = el;
this.cd = cd;
this._viewportRuler = _viewportRuler;
this.sRenderer = sRenderer;
this._platform = _platform;
this._ngZone = _ngZone;
/** @docs-private */
this.$priority = STYLE_PRIORITY;
/** @docs-private */
this.classes = this.sRenderer.renderSheet(STYLES, true);
this._tabsSubscription = Subscription.EMPTY;
this._timeoutIds = {};
/** Emits whenever the component is destroyed. */
this._destroy = new Subject();
this.selectedIndexOnChange = 'auto';
this.selectedIndexChange = new EventEmitter();
this.setAutoContrast();
this.animationDuration = 500;
}
ngOnChanges() {
if (this._isViewInitLoaded) {
this.updateStyle(this.tabsRef.nativeElement);
}
}
ngOnInit() {
if (this.selectedIndex == null) {
this.selectedIndex = 0;
}
this.renderer.addClass(this.el.nativeElement, this.classes.root);
const tabsIndicatorEl = this.tabsIndicator.nativeElement;
this.renderer.addClass(tabsIndicatorEl, this.classes.indicator);
/** Set default Color */
if (!this.indicatorColor && !this.bg && !this.textColor && !this.elevation) {
this.indicatorColor = DEFAULT_INDICATOR_COLOR;
this.bg = DEFAULT_BG;
this.elevation = DEFAULT_ELEVATION;
}
if (!this.headerPlacement) {
this.headerPlacement = DEFAULT_HEADER_PLACEMENT;
}
}
ngAfterContentInit() {
this._tabsSubscription = this.tabsList.changes.subscribe(() => {
if (this._selectedIndex !== this.selectedIndexOnChange) {
this.selectedIndex = this._findIndex(this.selectedIndex, this.selectedIndexOnChange);
}
this.cd.markForCheck();
});
}
ngAfterViewInit() {
this._isViewInitLoaded = true;
this.tabsList.changes
.pipe(switchMapTo(this._ngZone.onStable.asObservable().pipe(take(1))), takeUntil(this._destroy))
.subscribe(() => {
this._updateTabs();
});
this._updateTabs();
this.updateStyle(this.tabsRef.nativeElement);
if (this._platform.isBrowser) {
this._tabResizeSub = this._viewportRuler.change().subscribe(() => {
if (this._selectedTab) {
this._updateIndicator(this._selectedTab);
this._selectedTab._tabLabel._updateTabScroll();
}
});
}
}
ngOnDestroy() {
this._destroy.next();
this._destroy.complete();
this._tabsSubscription.unsubscribe();
if (this._tabResizeSub) {
this._tabResizeSub.unsubscribe();
}
this._clearTimeouts();
}
_findIndex(selectedIndex, index) {
if (!this.tabsList) {
return selectedIndex;
}
const indexOfLastTab = this.tabsList.length - 1;
const currentIndex = typeof index === 'number' ? index : selectedIndex;
return currentIndex < 0 ? 0 : currentIndex > indexOfLastTab ? indexOfLastTab : currentIndex;
}
_updateIndicator(currentTab, beforeTab) {
if (currentTab) {
if (beforeTab) {
beforeTab._renderer.removeAttribute(beforeTab._tabIndicator.nativeElement, 'class');
}
const el = currentTab._el.nativeElement;
const rects = el.getBoundingClientRect();
if (this.headerPlacement === XPosition.after || this.headerPlacement === XPosition.before) {
this.renderer.setStyle(this.tabsIndicator.nativeElement, 'height', `${rects.height}px`);
this.renderer.setStyle(this.tabsIndicator.nativeElement, 'top', `${el.offsetTop}px`);
this.renderer.removeStyle(this.tabsIndicator.nativeElement, 'width');
this.renderer.removeStyle(this.tabsIndicator.nativeElement, 'left');
}
else {
this.renderer.setStyle(this.tabsIndicator.nativeElement, 'width', `${rects.width}px`);
this.renderer.setStyle(this.tabsIndicator.nativeElement, 'left', `${el.offsetLeft}px`);
this.renderer.removeStyle(this.tabsIndicator.nativeElement, 'height');
this.renderer.removeStyle(this.tabsIndicator.nativeElement, 'top');
}
}
}
_markForCheck() {
this.cd.markForCheck();
}
_updateTabs() {
if (!this._isViewInitLoaded) {
return;
}
const tabsContents = this.tabContentList.toArray();
const tabsForUpdate = [];
this.tabsList.forEach((tab, index) => {
const tabContent = tabsContents[index].nativeElement;
if (this.selectedIndex === index || this._selectedBeforeIndex === index) {
tab._activeContent = true;
tabsForUpdate.push([tab, tabContent, index]);
}
else {
if (this.keepContent) {
this.renderer.addClass(tabContent, this.classes.hiddenContent);
}
}
});
this._ngZone.run(() => {
this._markForCheck();
});
this._ngZone.onStable.asObservable()
.pipe(take(1), takeUntil(this._destroy))
.subscribe(() => tabsForUpdate.forEach(parms => this._updateContentStyle(...parms)));
}
loadTemplate(tab, index) {
tab.index = index;
if (this.selectedIndex === tab.index) {
// set 0 if is null
this._selectedTab = tab;
Promise.resolve(null).then(() => {
// this._updateDynamicHeight(tabContent, index);
if (this._platform.isBrowser) {
this._updateIndicator(tab);
}
else {
// for server
const selectedBeforeTab = this._selectedBeforeTab;
if (selectedBeforeTab) {
this.renderer.removeClass(selectedBeforeTab._tabIndicator.nativeElement, this.classes.indicatorForServer);
}
this.renderer.addClass(this._selectedTab._tabIndicator.nativeElement, this.classes.indicatorForServer);
}
});
}
else if (this._selectedBeforeIndex === index) {
// Promise.resolve(null).then(() => this._updateDynamicHeight(tabContent, index));
}
tab._tabLabel._updateTabState();
if (this.keepContent) {
return tab.content;
}
if (tab._activeContent) {
return tab.content;
}
return null;
}
_getFlexDirection(val) {
let flexDirection;
if (val === YPosition.above || val === YPosition.below) {
flexDirection = 'row';
}
else {
flexDirection = 'column';
}
return flexDirection;
}
_updateContentStyle(tab, tabContent, index) {
if (this.selectedIndex === index || this._selectedBeforeIndex === index) {
const prevIndex = this._selectedBeforeIndex;
const currentIndex = this.selectedIndex;
const dynamicHeight = this.dynamicHeight && this._platform.isBrowser && prevIndex != null;
const contentInner = tabContent.firstElementChild;
const contentHeight = dynamicHeight ? contentInner.getBoundingClientRect().height : null;
const contentHeightPrev = dynamicHeight
? this.tabContentList.toArray()[prevIndex].nativeElement.firstElementChild.getBoundingClientRect().height
: null;
if (currentIndex === index) {
this.renderer.addClass(tabContent, this.classes.contentActive);
if (this.keepContent) {
this.renderer.removeClass(tabContent, this.classes.hiddenContent);
}
}
else {
this.renderer.removeClass(tabContent, this.classes.contentActive);
}
if (prevIndex == null || !this._platform.isBrowser || prevIndex === currentIndex) {
return;
}
this._clearTimeouts(index);
const { before } = this._theme.variables;
const isDirRow = this.headerPlacement === XPosition.after
|| this.headerPlacement === XPosition.before;
const x = before === 'left'
? 100
: isDirRow
? 100
: -100;
if (currentIndex === index) {
const sign = prevIndex < index ? 1 : -1;
const pos = isDirRow ? `0,${x * sign}%` : `${x * sign}%, 0`;
tabContent.style.overflow = 'hidden';
if (dynamicHeight) {
tabContent.style.height = `${contentHeightPrev}px`;
}
tabContent.style.transform = `translate3d(${pos}, 0)`;
enforceStyleRecalculation(tabContent);
tabContent.style.transition = `${this.animationDuration}ms cubic-bezier(0.35, 0, 0.25, 1)`;
tabContent.style.transform = `translate3d(0%, 0, 0)`;
if (dynamicHeight) {
tabContent.style.height = `${contentHeight}px`;
}
}
else {
const sign = currentIndex < index ? 1 : -1;
const pos = isDirRow ? `0,${x * sign}%` : `${x * sign}%, 0`;
tabContent.style.overflow = 'hidden';
tabContent.style.transform = `translate3d(0%, 0, 0)`;
enforceStyleRecalculation(tabContent);
tabContent.style.transition = `${this.animationDuration}ms cubic-bezier(0.35, 0, 0.25, 1)`;
tabContent.style.transform = `translate3d(${pos}, 0)`;
}
this._runTimeoutOutsideZone(index, () => {
tabContent.style.transform = ``;
tabContent.style.transition = ``;
tabContent.style.overflow = ``;
if (dynamicHeight) {
tabContent.style.height = ``;
}
if (currentIndex !== index) {
if (this.keepContent) {
this.renderer.addClass(tabContent, this.classes.hiddenContent);
}
tab._activeContent = false;
this._ngZone.run(() => this._markForCheck());
}
}, this.animationDuration);
}
}
/** Runs a timeout outside of the Angular zone to avoid triggering the change detection. */
_runTimeoutOutsideZone(index, fn, delay = 0) {
this._ngZone.runOutsideAngular(() => this._timeoutIds[`_${index}`] = window.setTimeout(fn, delay));
}
_clearTimeouts(tabIndex) {
if (tabIndex != null) {
const key = `_${tabIndex}`;
if (this._timeoutIds[key] != null) {
window.clearTimeout(this._timeoutIds[key]);
delete this._timeoutIds[key];
}
}
else {
Object.keys(this._timeoutIds)
.forEach(key => window.clearTimeout(this._timeoutIds[`_${key}`]));
}
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.10", ngImport: i0, type: LyTabs, deps: [{ token: i1.LyTheme2 }, { token: i0.Renderer2 }, { token: i0.ElementRef }, { token: i0.ChangeDetectorRef }, { token: i2.ViewportRuler }, { token: i1.StyleRenderer }, { token: i3.Platform }, { token: i0.NgZone }], target: i0.ɵɵFactoryTarget.Component }); }
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.2.10", type: LyTabs, isStandalone: false, selector: "ly-tabs", inputs: { bg: "bg", elevation: "elevation", shadowColor: "shadowColor", selectedIndexOnChange: "selectedIndexOnChange", keepContent: "keepContent", animationDuration: "animationDuration", dynamicHeight: "dynamicHeight", scrollable: "scrollable", indicatorColor: "indicatorColor", headerPlacement: "headerPlacement", alignTabs: "alignTabs", textColor: "textColor", selectedIndex: "selectedIndex" }, outputs: { selectedIndexChange: "selectedIndexChange" }, providers: [
StyleRenderer
], queries: [{ propertyName: "tabsList", predicate: i0.forwardRef(() => LyTab) }], viewQueries: [{ propertyName: "tabsRef", first: true, predicate: ["tabs"], descendants: true, static: true }, { propertyName: "tabContents", first: true, predicate: ["tabContents"], descendants: true, static: true }, { propertyName: "tabsIndicator", first: true, predicate: ["tabsIndicator"], descendants: true, read: ElementRef, static: true }, { propertyName: "tabContentList", predicate: ["tabContent"], descendants: true }], exportAs: ["lyTabs"], usesInheritance: true, usesOnChanges: true, ngImport: i0, template: "<div #tabs [className]=\"classes.labelsContainer\">\n <div [className]=\"classes.labels\">\n <ng-content></ng-content>\n <span #tabsIndicator></span>\n </div>\n</div>\n<div [className]=\"classes.contentContainer\">\n <div [className]=\"classes.contents\" #tabContents>\n <div #tabContent *ngFor=\"let item of tabsList; index as x\" [className]=\"classes.content\">\n <div [className]=\"classes.contentInner\">\n <ng-template\n [cdkPortalOutlet]=\"loadTemplate(item, x)\"\n ></ng-template>\n </div>\n </div>\n </div>\n</div>\n", dependencies: [{ kind: "directive", type: i4.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i5.CdkPortalOutlet, selector: "[cdkPortalOutlet]", inputs: ["cdkPortalOutlet"], outputs: ["attached"], exportAs: ["cdkPortalOutlet"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None }); }
}
__decorate([
Style(val => (theme, ref) => {
const __ = ref.selectorsOf(STYLES);
return (_className) => `${_className} ${__.indicator}{color:${theme.colorOf(val)};}`;
})
], LyTabs.prototype, "indicatorColor", void 0);
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.10", ngImport: i0, type: LyTabs, decorators: [{
type: Component,
args: [{ selector: 'ly-tabs', changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, exportAs: 'lyTabs', inputs: [
'bg', 'elevation', 'shadowColor'
], providers: [
StyleRenderer
], standalone: false, template: "<div #tabs [className]=\"classes.labelsContainer\">\n <div [className]=\"classes.labels\">\n <ng-content></ng-content>\n <span #tabsIndicator></span>\n </div>\n</div>\n<div [className]=\"classes.contentContainer\">\n <div [className]=\"classes.contents\" #tabContents>\n <div #tabContent *ngFor=\"let item of tabsList; index as x\" [className]=\"classes.content\">\n <div [className]=\"classes.contentInner\">\n <ng-template\n [cdkPortalOutlet]=\"loadTemplate(item, x)\"\n ></ng-template>\n </div>\n </div>\n </div>\n</div>\n" }]
}], ctorParameters: () => [{ type: i1.LyTheme2 }, { type: i0.Renderer2 }, { type: i0.ElementRef }, { type: i0.ChangeDetectorRef }, { type: i2.ViewportRuler }, { type: i1.StyleRenderer }, { type: i3.Platform }, { type: i0.NgZone }], propDecorators: { tabsRef: [{
type: ViewChild,
args: ['tabs', { static: true }]
}], tabContents: [{
type: ViewChild,
args: ['tabContents', { static: true }]
}], tabsIndicator: [{
type: ViewChild,
args: ['tabsIndicator', { static: true, read: ElementRef }]
}], selectedIndexOnChange: [{
type: Input
}], keepContent: [{
type: Input
}], animationDuration: [{
type: Input
}], dynamicHeight: [{
type: Input
}], scrollable: [{
type: Input
}], indicatorColor: [{
type: Input
}], headerPlacement: [{
type: Input
}], alignTabs: [{
type: Input
}], textColor: [{
type: Input
}], selectedIndex: [{
type: Input
}], selectedIndexChange: [{
type: Output
}], tabsList: [{
type: ContentChildren,
args: [forwardRef(() => LyTab)]
}], tabContentList: [{
type: ViewChildren,
args: ['tabContent']
}] } });
class LyTab {
/** @docs-private */
get content() {
return this._contentPortal;
}
constructor(_tabs, _renderer, _el, sRenderer, _platform, _viewContainerRef) {
this._tabs = _tabs;
this._renderer = _renderer;
this._el = _el;
this.sRenderer = sRenderer;
this._platform = _platform;
this._viewContainerRef = _viewContainerRef;
this._isBrowser = this._platform.isBrowser;
/** Portal that will be the hosted content of the tab */
this._contentPortal = null;
}
ngOnInit() {
this._renderer.addClass(this._el.nativeElement, this._tabs.classes.tab);
this._contentPortal = new TemplatePortal(this._templateRefLazy || this._templateRef, this._viewContainerRef);
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.10", ngImport: i0, type: LyTab, deps: [{ token: LyTabs }, { token: i0.Renderer2 }, { token: i0.ElementRef }, { token: i1.StyleRenderer }, { token: i3.Platform }, { token: i0.ViewContainerRef }], target: i0.ɵɵFactoryTarget.Component }); }
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.2.10", type: LyTab, isStandalone: false, selector: "ly-tab", providers: [
StyleRenderer
], queries: [{ propertyName: "_templateRefLazy", first: true, predicate: LyTabContent, descendants: true, read: TemplateRef, static: true }, { propertyName: "_tabLabel", first: true, predicate: i0.forwardRef(() => LyTabLabel), descendants: true, static: true }], viewQueries: [{ propertyName: "_templateRef", first: true, predicate: ["_templateNgContent"], descendants: true, static: true }, { propertyName: "_tabIndicator", first: true, predicate: ["tabIndicator"], descendants: true }], ngImport: i0, template: "<ng-content select=\"ly-tab-label\"></ng-content>\n<ng-content select=\"[ly-tab-label]\"></ng-content>\n<ng-content select=\"[ly-tab-label-native]\"></ng-content>\n<div></div>\n<span *ngIf=\"!_isBrowser\" #tabIndicator></span>\n<ng-template #_templateNgContent>\n <ng-content></ng-content>\n</ng-template>", dependencies: [{ kind: "directive", type: i4.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.10", ngImport: i0, type: LyTab, decorators: [{
type: Component,
args: [{ selector: 'ly-tab', changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, providers: [
StyleRenderer
], standalone: false, template: "<ng-content select=\"ly-tab-label\"></ng-content>\n<ng-content select=\"[ly-tab-label]\"></ng-content>\n<ng-content select=\"[ly-tab-label-native]\"></ng-content>\n<div></div>\n<span *ngIf=\"!_isBrowser\" #tabIndicator></span>\n<ng-template #_templateNgContent>\n <ng-content></ng-content>\n</ng-template>" }]
}], ctorParameters: () => [{ type: LyTabs }, { type: i0.Renderer2 }, { type: i0.ElementRef }, { type: i1.StyleRenderer }, { type: i3.Platform }, { type: i0.ViewContainerRef }], propDecorators: { _templateRefLazy: [{
type: ContentChild,
args: [LyTabContent, { read: TemplateRef, static: true }]
}], _templateRef: [{
type: ViewChild,
args: ['_templateNgContent', { static: true }]
}], _tabIndicator: [{
type: ViewChild,
args: ['tabIndicator']
}], _tabLabel: [{
type: ContentChild,
args: [forwardRef(() => LyTabLabel), { static: true }]
}] } });
class LyTabLabel extends LyButton {
get active() {
return this._active;
}
set active(val) {
const newVal = coerceBooleanProperty(val);
if (newVal && val !== this.active) {
Promise.resolve(null).then(() => this._tabs.selectedIndex = this._tab.index);
}
}
_onClickTab() {
if (!this.disabled) {
this._tabs.selectedIndex = this._tab.index;
}
}
constructor(_el, _renderer, _theme, _ngZone, _rippleService, _focusMonitor, sRenderer, _tab, _tabs, platform) {
super(_el, _renderer, _theme, _ngZone, _rippleService, _focusMonitor, sRenderer, platform, null);
this.sRenderer = sRenderer;
this._tab = _tab;
this._tabs = _tabs;
this._isBrowser = platform.isBrowser;
}
ngOnInit() {
this._renderer.addClass(this._el.nativeElement, this._tabs.classes.label);
// set default disable ripple
if (this.disableRipple == null) {
this.disableRipple = DEFAULT_DISABLE_RIPPLE;
}
}
_updateTabState() {
// update styles for active tab
if (this._tabs._selectedIndex === this._tab.index) {
if (!this._activeTabStyle) {
this._activeTabStyle = true;
this._renderer.addClass(this._el.nativeElement, this._tabs.classes.labelActive);
this._updateTabScroll();
}
}
else if (this._activeTabStyle) {
this._activeTabStyle = false;
this._renderer.removeClass(this._el.nativeElement, this._tabs.classes.labelActive);
}
}
_updateTabScroll() {
if (this._isBrowser && this._tabs.scrollable) {
const tab = this._tab._el.nativeElement;
const tabContainer = this._tabs.tabsRef.nativeElement;
if (tabContainer.scrollWidth !== tabContainer.offsetWidth) {
const dir = this._theme.variables.direction;
const max = tabContainer.scrollWidth - tabContainer.offsetWidth;
const offsetBefore = dir === Dir.rtl
? max + tab.offsetLeft
: tab.offsetLeft;
const l = offsetBefore + tab.offsetWidth / 2 - tabContainer.offsetWidth / 2;
const newVal = l >= max ? max : l <= 0 ? 0 : l;
scrollWithAnimation(this._tabs.tabsRef.nativeElement, newVal, 350, 'x');
}
}
}
ngAfterViewInit() { }
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.10", ngImport: i0, type: LyTabLabel, deps: [{ token: i0.ElementRef }, { token: i0.Renderer2 }, { token: i1.LyTheme2 }, { token: i0.NgZone }, { token: i1.LyRippleService }, { token: i6.FocusMonitor }, { token: i1.StyleRenderer }, { token: LyTab, optional: true }, { token: LyTabs, optional: true }, { token: i3.Platform }], target: i0.ɵɵFactoryTarget.Component }); }
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.2.10", type: LyTabLabel, isStandalone: false, selector: "button[ly-tab-label], a[ly-tab-label]", inputs: { bg: "bg", color: "color", raised: "raised", disabled: "disabled", outlined: "outlined", elevation: "elevation", shadowColor: "shadowColor", disableRipple: "disableRipple", active: "active" }, host: { listeners: { "click": "_onClickTab()" } }, providers: [
StyleRenderer
], viewQueries: [{ propertyName: "_rippleContainer", first: true, predicate: ["rippleContainer"], descendants: true }], usesInheritance: true, ngImport: i0, template: "<span [className]=\"classes.content\">\n <ng-content></ng-content>\n</span>\n<div *ngIf=\"_isBrowser\" #rippleContainer [className]=\"_rippleService.classes.container\"></div>\n", dependencies: [{ kind: "directive", type: i4.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }] }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.10", ngImport: i0, type: LyTabLabel, decorators: [{
type: Component,
args: [{ selector: 'button[ly-tab-label], a[ly-tab-label]', inputs: [
'bg',
'color',
'raised',
'disabled',
'outlined',
'elevation',
'shadowColor',
'disableRipple'
], providers: [
StyleRenderer
], standalone: false, template: "<span [className]=\"classes.content\">\n <ng-content></ng-content>\n</span>\n<div *ngIf=\"_isBrowser\" #rippleContainer [className]=\"_rippleService.classes.container\"></div>\n" }]
}], ctorParameters: () => [{ type: i0.ElementRef }, { type: i0.Renderer2 }, { type: i1.LyTheme2 }, { type: i0.NgZone }, { type: i1.LyRippleService }, { type: i6.FocusMonitor }, { type: i1.StyleRenderer }, { type: LyTab, decorators: [{
type: Optional
}] }, { type: LyTabs, decorators: [{
type: Optional
}] }, { type: i3.Platform }], propDecorators: { active: [{
type: Input
}], _rippleContainer: [{
type: ViewChild,
args: ['rippleContainer']
}], _onClickTab: [{
type: HostListener,
args: ['click']
}] } });
/** Enforces a style recalculation of a DOM element by computing its styles. */
function enforceStyleRecalculation(element) {
window.getComputedStyle(element).getPropertyValue('opacity');
}
class LyTabsModule {
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.10", ngImport: i0, type: LyTabsModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); }
static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "19.2.10", ngImport: i0, type: LyTabsModule, declarations: [LyTabs, LyTab, LyTabLabel, LyTabContent], imports: [LyThemeModule,
CommonModule,
LyCommonModule,
NgTranscludeModule,
PortalModule], exports: [LyCommonModule, LyTabs, LyTab, LyTabLabel, LyTabContent] }); }
static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "19.2.10", ngImport: i0, type: LyTabsModule, imports: [LyThemeModule,
CommonModule,
LyCommonModule,
NgTranscludeModule,
PortalModule, LyCommonModule] }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.10", ngImport: i0, type: LyTabsModule, decorators: [{
type: NgModule,
args: [{
imports: [
LyThemeModule,
CommonModule,
LyCommonModule,
NgTranscludeModule,
PortalModule
],
exports: [LyCommonModule, LyTabs, LyTab, LyTabLabel, LyTabContent],
declarations: [LyTabs, LyTab, LyTabLabel, LyTabContent]
}]
}] });
/**
* Generated bundle index. Do not edit.
*/
export { LyTab, LyTabContent, LyTabLabel, LyTabLabelBase, LyTabLabelMixinBase, LyTabs, LyTabsBase, LyTabsMixinBase, LyTabsModule, STYLES };
//# sourceMappingURL=alyle-ui-tabs.mjs.map