Skip to content

Commit

Permalink
feat(tabs): support tabs with async
Browse files Browse the repository at this point in the history
  • Loading branch information
alyleui committed Aug 16, 2018
1 parent ab2e2f4 commit dc08d0e
Show file tree
Hide file tree
Showing 4 changed files with 174 additions and 91 deletions.
189 changes: 120 additions & 69 deletions src/lib/tabs/tabs.clasess.service.ts
Original file line number Diff line number Diff line change
@@ -1,79 +1,130 @@
import { Injectable } from '@angular/core';
import { LyTheme2 } from '@alyle/ui';

const tabsStyles = {
root: {
display: 'block',
overflow: 'hidden'
},
tab: {
position: 'relative',
display: 'inline-flex'
},
tabsLabels: {
display: 'flex',
position: 'relative',
'flex-grow': 1,
overflow: 'hidden'
},
tabLabel: {
'min-width': '72px',
padding: '0 24px',
cursor: 'pointer',
height: '48px',
display: 'inline-flex',
'justify-content': 'center',
'align-items': 'center'
},
tabContents: {
display: 'flex',
transition: '450ms cubic-bezier(.1, 1, 0.5, 1)',
'will-change': 'transform'
},
tabContent: {
width: '100%',
'flex-shrink': 0,
position: 'relative'
},
tabsIndicator: {
position: 'absolute',
transition: '450ms cubic-bezier(.1, 1, 0.5, 1)',
bottom: 0,
height: '2px',
left: 0,
background: 'currentColor'
},
tabsIndicatorForServer: {
width: '100%'
}
};

@Injectable({
providedIn: 'root'
})
export class LyTabsClassesService {
tabs = this.theme.setUpStyle(
'k-tabs',
() => (
`display:block;` +
`overflow:hidden;`
)
);
tabsLabels = this.theme.setUpStyle(
'k-tab-labels',
() => (
`display: flex;` +
`position: relative;` +
`flex-grow: 1;` +
`overflow: hidden;`
)
);
tab = this.theme.setUpStyle(
'k-tab',
() => (
`position: relative;` +
`display: inline-flex;`
)
);
tabLabel = this.theme.setUpStyle(
'k-tab-label',
() => (
`min-width: 72px;` +
`padding: 0 24px;` +
`cursor: pointer;` +
`height: 48px;` +
`display: inline-flex;` +
`justify-content: center;` +
`align-items: center;`
)
);
tabContents = this.theme.setUpStyle(
'k-tab-contents',
() => (
`display: flex;` +
`transition: 450ms cubic-bezier(.1, 1, 0.5, 1);` +
`will-change: transform;`
)
);
tabContent = this.theme.setUpStyle(
'k-tab-content',
() => (
`width: 100%;` +
`flex-shrink: 0;` +
`position: relative;`
)
);
tabsIndicator = this.theme.setUpStyle(
'k-tabs-indicator',
() => (
`position: absolute;` +
`transition: 450ms cubic-bezier(.1, 1, 0.5, 1);` +
`bottom: 0;` +
`height: 2px;` +
`left: 0;` +
`background: currentColor;`
)
);
tabsIndicatorForServer = this.theme.setUpStyle(
'k-tabs-indicator-server',
() => (
`width: 100%;`
)
);
// tabs = this.theme.setUpStyle(
// 'k-tabs',
// () => (
// `display:block;` +
// `overflow:hidden;`
// )
// );
// tabsLabels = this.theme.setUpStyle(
// 'k-tab-labels',
// () => (
// `display: flex;` +
// `position: relative;` +
// `flex-grow: 1;` +
// `overflow: hidden;`
// )
// );
// tab = this.theme.setUpStyle(
// 'k-tab',
// () => (
// `position: relative;` +
// `display: inline-flex;`
// )
// );
// tabLabel = this.theme.setUpStyle(
// 'k-tab-label',
// () => (
// `min-width: 72px;` +
// `padding: 0 24px;` +
// `cursor: pointer;` +
// `height: 48px;` +
// `display: inline-flex;` +
// `justify-content: center;` +
// `align-items: center;`
// )
// );
// tabContents = this.theme.setUpStyle(
// 'k-tab-contents',
// () => (
// `display: flex;` +
// `transition: 450ms cubic-bezier(.1, 1, 0.5, 1);` +
// `will-change: transform;`
// )
// );
// tabContent = this.theme.setUpStyle(
// 'k-tab-content',
// () => (
// `width: 100%;` +
// `flex-shrink: 0;` +
// `position: relative;`
// )
// );
// tabsIndicator = this.theme.setUpStyle(
// 'k-tabs-indicator',
// () => (
// `position: absolute;` +
// `transition: 450ms cubic-bezier(.1, 1, 0.5, 1);` +
// `bottom: 0;` +
// `height: 2px;` +
// `left: 0;` +
// `background: currentColor;`
// )
// );
// tabsIndicatorForServer = this.theme.setUpStyle(
// 'k-tabs-indicator-server',
// () => (
// `width: 100%;`
// )
// );
classes;
constructor(
private theme: LyTheme2
) { }
) {
console.log('name', theme.config.name);
this.classes = theme.addStyleSheet(tabsStyles, 'lyTabs');
}
}
6 changes: 3 additions & 3 deletions src/lib/tabs/tabs.directive.html
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
<div [className]="classes.tabsLabels">
<div [withClass]="classes.tabsLabels">
<span #tabsIndicator></span>
<ng-content></ng-content>
</div>
<div [className]="classes.tabContents" #tabContents>
<div [withClass]="classes.tabContents" #tabContents>
<ng-template ngFor let-item [ngForOf]="tabsList" let-x="index">
<div [className]="classes.tabContent">
<div [withClass]="classes.tabContent">
<ng-template [ngTransclude]="loadTemplate(item, x)"></ng-template>
</div>
</ng-template>
Expand Down
65 changes: 49 additions & 16 deletions src/lib/tabs/tabs.directive.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,14 @@ import {
ElementRef,
OnInit,
ViewEncapsulation,
AfterViewInit
AfterViewInit,
AfterContentInit,
OnDestroy
} from '@angular/core';
import { LyTabContent } from './tab-content.directive';
import { LyTabsClassesService } from './tabs.clasess.service';
import { UndefinedValue, Undefined, LyTheme2, Platform } from '@alyle/ui';
import { Subscription } from 'rxjs';

@Component({
selector: 'ly-tabs',
Expand All @@ -30,17 +33,20 @@ import { UndefinedValue, Undefined, LyTheme2, Platform } from '@alyle/ui';
encapsulation: ViewEncapsulation.None,
exportAs: 'lyTabs'
})
export class LyTabs implements OnInit, AfterViewInit {
_selectedIndex: number | Undefined = UndefinedValue;
export class LyTabs implements OnInit, AfterViewInit, AfterContentInit, OnDestroy {
_selectedIndex = 0;
_selectedBeforeIndex: number;
_selectedRequireCheck: boolean;
_selectedTab: LyTab;
_selectedBeforeTab: LyTab;
private _tabsSubscription = Subscription.EMPTY;
private _isViewInitLoaded: boolean;
private _withColor: string;
private _withColorClass: string;
readonly classes;
@ViewChild('tabContents') tabContents: ElementRef;
@ViewChild('tabsIndicator') tabsIndicator: ElementRef;
@Input() selectedIndexOnChange: 'auto' | number = 'auto';
@Input()
set withColor(val: string) {
if (val !== this.withColor) {
Expand All @@ -58,15 +64,15 @@ export class LyTabs implements OnInit, AfterViewInit {
set selectedIndex(val: number) {
if (val !== this.selectedIndex) {
this._selectedBeforeIndex = this._selectedIndex as number;
this._selectedIndex = val;
this._selectedIndex = this._findIndex(val, 'auto');
this._selectedBeforeTab = this._selectedTab;
this.selectedIndexChange.emit(val);
this.selectedIndexChange.emit(this._selectedIndex);
this._updateIndicator(this._selectedTab, this._selectedBeforeTab);

if (this._selectedRequireCheck) {
this.markForCheck();
}
this.renderer.setStyle(this.tabContents.nativeElement, 'transform', `translate3d(${val * -100}%,0,0)`);
this.renderer.setStyle(this.tabContents.nativeElement, 'transform', `translate3d(${this._selectedIndex * -100}%,0,0)`);
}
}
get selectedIndex() {
Expand All @@ -77,15 +83,17 @@ export class LyTabs implements OnInit, AfterViewInit {
@ContentChildren(forwardRef(() => LyTab)) tabsList: QueryList<LyTab>;

constructor(
public classes: LyTabsClassesService,
tabsService: LyTabsClassesService,
private theme: LyTheme2,
private renderer: Renderer2,
private el: ElementRef,
private cd: ChangeDetectorRef
) { }
) {
this.classes = tabsService.classes;
}

ngOnInit() {
this.renderer.addClass(this.el.nativeElement, this.classes.tabs);
this.renderer.addClass(this.el.nativeElement, this.classes.root);
const tabsIndicatorEl = this.tabsIndicator.nativeElement;
this.renderer.addClass(tabsIndicatorEl, this.classes.tabsIndicator);
/** Set default Color */
Expand All @@ -97,6 +105,26 @@ export class LyTabs implements OnInit, AfterViewInit {
ngAfterViewInit() {
this._isViewInitLoaded = true;
}
ngAfterContentInit() {
this._tabsSubscription = this.tabsList.changes.subscribe(() => {
if (this._selectedIndex !== this.selectedIndexOnChange) {
this.selectedIndex = this._findIndex(this.selectedIndex, this.selectedIndexOnChange);
}
this.cd.markForCheck();
});
}
ngOnDestroy() {
this._tabsSubscription.unsubscribe();
}

private _findIndex(selectedIndex: number, index: string | number) {
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;
}

private _updateIndicator(currentTab: LyTab, beforeTab?: LyTab): void {
const currentIndex = this.selectedIndex;
Expand Down Expand Up @@ -136,10 +164,10 @@ export class LyTabs implements OnInit, AfterViewInit {
return null;
}
tab.index = index;
if (this.selectedIndex === UndefinedValue) {
if (this.selectedIndex === tab.index) {
// set 0 if is null
this._selectedTab = tab;
this.selectedIndex = 0;
this._updateIndicator(tab);
} else if (!this._isViewInitLoaded && this.selectedIndex === tab.index) {
this._selectedTab = tab;
/** Apply style for tabIndicator server */
Expand Down Expand Up @@ -178,6 +206,7 @@ export class LyTabs implements OnInit, AfterViewInit {
export class LyTab implements OnInit, AfterViewInit {
index: number;
loaded: boolean;
protected readonly classes;
@ContentChild(LyTabContent, { read: TemplateRef }) templateRefLazy: TemplateRef<LyTabContent>;
@ViewChild(TemplateRef) templateRef: TemplateRef<any>;
@ViewChild('tabIndicator') tabIndicator: ElementRef;
Expand All @@ -187,17 +216,20 @@ export class LyTab implements OnInit, AfterViewInit {
}

constructor(
private tabsService: LyTabsClassesService,
private tabs: LyTabs,
public _renderer: Renderer2,
public _el: ElementRef,
) { }
) {
this.classes = this.tabsService.classes;
}

ngOnInit() {
this._renderer.addClass(this._el.nativeElement, this.tabs.classes.tab);
this._renderer.addClass(this._el.nativeElement, this.classes.tab);
}

ngAfterViewInit() {
this._renderer.addClass(this.tabIndicator.nativeElement, this.tabs.classes.tabsIndicator);
this._renderer.addClass(this.tabIndicator.nativeElement, this.classes.tabsIndicator);
}
}

Expand All @@ -210,11 +242,11 @@ export class LyTabLabel implements OnInit {
constructor(
private renderer: Renderer2,
private el: ElementRef,
private classes: LyTabsClassesService
private tabsService: LyTabsClassesService
) { }

ngOnInit() {
this.renderer.addClass(this.el.nativeElement, this.classes.tabLabel);
this.renderer.addClass(this.el.nativeElement, this.tabsService.classes.tabLabel);
}
}
/**
Expand Down Expand Up @@ -243,4 +275,5 @@ export class LyTabLabel implements OnInit {
* => native: no aplica los estilos predeterminados, default undefined
* => disabled: Disable/enable a tab, default undefined
* => isActive: Si la pestaña está actualmente activa., default undefined
* => selectedIndexOnChange, default: auto, opts: number, with auto, the selectedIndex = current o current-1 or latest
*/
Loading

0 comments on commit dc08d0e

Please sign in to comment.