Skip to content

Commit

Permalink
init
Browse files Browse the repository at this point in the history
  • Loading branch information
ihadeed committed Mar 18, 2017
0 parents commit 9a7e4a6
Show file tree
Hide file tree
Showing 12 changed files with 301 additions and 0 deletions.
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
node_modules
dist
aot
.idea
7 changes: 7 additions & 0 deletions .npmignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
src
node_modules
.gitignore
.npmignore
tsconfig.json
.idea
aot
32 changes: 32 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
{
"name": "ionic2-super-tabs",
"version": "0.1.0",
"description": "",
"main": "dist/index.js",
"typings": "dist/index.d.ts",
"scripts": {
"build": "rm -rf aot dist && ngc",
"copy:scss": "cd src && copyfiles '**/*.scss' ../dist"
},
"author": "Ibby Hadeed <[email protected]>",
"license": "MIT",
"devDependencies": {
"@angular/common": "2.4.8",
"@angular/compiler": "2.4.8",
"@angular/compiler-cli": "2.4.8",
"@angular/core": "2.4.8",
"@angular/forms": "^2.4.8",
"@angular/http": "2.4.8",
"@angular/platform-browser": "2.4.8",
"@angular/platform-browser-dynamic": "2.4.8",
"@angular/platform-server": "2.4.8",
"copy": "^0.3.0",
"copyfiles": "^1.2.0",
"ionic-angular": "2.2.0",
"ionicons": "3.0.0",
"rxjs": "5.0.1",
"sw-toolbox": "3.4.0",
"typescript": "2.0.9",
"zone.js": "0.7.2"
}
}
Empty file.
5 changes: 5 additions & 0 deletions src/components/super-tab/super-tab.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
super-tab {
> ion-nav {
position: static;
}
}
22 changes: 22 additions & 0 deletions src/components/super-tab/super-tab.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import { Component, Input } from '@angular/core';

@Component({
selector: 'super-tab',
template: ''
})
export class SuperTabComponent {

@Input()
tabRoot: any;

@Input()
title: string;

@Input()
icon: string;

constructor() {
console.log('Hello SuperTab Component');
}

}
Empty file.
35 changes: 35 additions & 0 deletions src/components/super-tabs/super-tabs.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
super-tabs {

ion-segment.segment.segment-md {
ion-segment-button {
border-bottom: 0;
height: inherit;
ion-icon {
display: block;
}
}

+ .slide {
bottom: 0;
position: absolute;
z-index: 2;
height: 2px;
background: map_get($colors, light);
&.ease {
transition: left .25s ease-in;
}
}

}

ion-slides {
text-align: inherit;
font-size: inherit;
ion-slide, ion-slide .slide-zoom, .swiper-slide {
text-align: inherit;
font-size: inherit;
}
}


}
151 changes: 151 additions & 0 deletions src/components/super-tabs/super-tabs.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,151 @@
import {Component, ContentChildren, Input, QueryList, ViewChild} from '@angular/core';
import {SuperTabComponent} from "../super-tab/super-tab";
import {Header, Platform, Slides} from "ionic-angular";

/*
Generated class for the SuperTabs component.
See https://angular.io/docs/ts/latest/api/core/index/ComponentMetadata-class.html
for more info on Angular 2 Components.
*/
@Component({
selector: 'super-tabs',
template: `
<ion-header>
<ion-navbar color="dark">
<ion-title>{{pageTitle}}</ion-title>
</ion-navbar>
<ion-toolbar color="dark">
<ion-segment color="light" [(ngModel)]="selectedTabIndex">
<ion-segment-button *ngFor="let tab of tabs; let i = index" [value]="i" (ionSelect)="onTabSelect(i)">
<ion-icon *ngIf="tab.icon" [name]="tab.icon"></ion-icon>
{{tab.title}}
</ion-segment-button>
</ion-segment>
<div class="slide" #slide [style.left]="slidePosition" [class.ease]="shouldSlideEase" [style.width]="slideWidth"></div>
</ion-toolbar>
</ion-header>
<ion-slides [style.margin-top]="headerHeight + 'px'" [style.height]="slidesHeight + 'px'" (ionSlideDrag)="onDrag($event)" (ionSlideWillChange)="onSlideWillChange()" (ionSlideDidChange)="onSlideDidChange()" [initialSlide]="selectedTabIndex">
<ion-slide *ngFor="let tab of tabs">
<ion-nav [root]="tab.tabRoot"></ion-nav>
</ion-slide>
</ion-slides>
`
})
export class SuperTabsComponent {

@ContentChildren(SuperTabComponent) superTabs: QueryList<SuperTabComponent>;

tabs: SuperTabComponent[] = [];

@ViewChild(Slides) slides: Slides;

@ViewChild(Header) header: Header;
headerHeight: number = 0;
slidesHeight: number = 0;

_selectedTabIndex = 0;
@Input()
set selectedTabIndex(val: number) {
if (val >= this.tabs.length) {
return;
}
this._selectedTabIndex = val;
let slidePosition = val * this.slides.renderedWidth / this.tabs.length;
this.slidePosition = slidePosition <= this.maxSlidePosition ? slidePosition + 'px' : this.maxSlidePosition + 'px';
this.pageTitle = this.tabs[this.selectedTabIndex].title;
}

get selectedTabIndex(): number {
return this._selectedTabIndex;
}

maxSlidePosition: number;
slidePosition = '0';
slideWidth = '0';
shouldSlideEase: boolean = false;
pageTitle: string = '';

constructor(private platform: Platform) {
console.log('Hello SuperTabs Component');
}

/**
* We listen to drag events to move the "slide" thingy along with the slides
* // TODO figure out a way to reset the "slide" position after the user is done dragging. ATM it gets stuck if the user swipes partially without changing the tab.
* @param ev
*/
onDrag(ev: Slides) {
if (ev._translate > 0) return;
const percentage = Math.abs(ev._translate / ev._virtualSize);
const singleSlideSize = ev._renderedSize;

let slidePosition = percentage * singleSlideSize;

if (slidePosition > this.maxSlidePosition) {
slidePosition = this.maxSlidePosition;
}

this.slidePosition = slidePosition + 'px';
}

/**
* The slide will change because the user stopped dragging, or clicked on a segment button
* Let's make sure the segment button is in alignment with the slides
* Also, lets animate the "slide" element
*/
onSlideWillChange() {
if (this.slides.getActiveIndex() <= this.tabs.length) {
this.shouldSlideEase = true;
this.selectedTabIndex = this.slides.getActiveIndex();
}
}

/**
* We need to disable animation after the slide is done changing
* Any further movement should happen instantly as the user swipes through the tabs
*/
onSlideDidChange() {
this.shouldSlideEase = false;
}

/**
* Runs when the user clicks on a segment button
* @param index
*/
onTabSelect(index: number) {
if (index <= this.tabs.length) {
this.slides.slideTo(index);
}
}

ngAfterViewInit() {
// take the tabs from the query and put them in a regular array to make life easier
this.superTabs.forEach(tab => this.tabs.push(tab));

// set page title based on the selected page
this.pageTitle = this.tabs[this.selectedTabIndex].title;

// the width of the "slide", should be equal to the width of a single `ion-segment-button`
// we'll just calculate it instead of querying for a segment button
this.slideWidth = this.platform.width() / this.tabs.length + 'px';

// we need this to make sure the "slide" thingy doesn't move outside the screen
this.maxSlidePosition = this.platform.width() - (this.platform.width() / this.tabs.length);

// we waiting for 100ms just to give `ion-icon` some time to decide if they want to show up or not
// if we check height immediately, we will get the height of the header without the icons
setTimeout(this.setHeights.bind(this), 100);

}

/**
* Sets the height of ion-slides and it's position from the top of the page
*/
private setHeights() {
this.headerHeight = this.header.getNativeElement().offsetHeight;
this.slidesHeight = this.platform.height() - this.headerHeight;
}


}
3 changes: 3 additions & 0 deletions src/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export * from './components/super-tab/super-tab';
export * from './components/super-tabs/super-tabs';
export * from './super-tabs.module';
19 changes: 19 additions & 0 deletions src/super-tabs.module.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { NgModule } from '@angular/core';
import { IonicModule } from 'ionic-angular';
import {SuperTabComponent} from "./components/super-tab/super-tab";
import {SuperTabsComponent} from "./components/super-tabs/super-tabs";

@NgModule({
declarations: [
SuperTabComponent,
SuperTabsComponent
],
imports: [
IonicModule
],
exports: [
SuperTabComponent,
SuperTabsComponent
]
})
export class SuperTabsModule { }
23 changes: 23 additions & 0 deletions tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
{
"compilerOptions": {
"module": "es2015",
"target": "es5",
"moduleResolution": "node",
"sourceMap": true,
"declaration": true,
"noImplicitAny": false,
"experimentalDecorators": true,
"lib": [
"dom",
"es2015"
],
"outDir": "dist"
},
"exclude": [
"node_modules",
"dist"
],
"angularCompilerOptions": {
"genDir": "aot"
}
}

0 comments on commit 9a7e4a6

Please sign in to comment.