diff --git a/gulpfile.js b/gulpfile.js
index ffd1c91d99..e565a233fc 100644
--- a/gulpfile.js
+++ b/gulpfile.js
@@ -1,6 +1,6 @@
-/////
+//
// Mostly stolen from https://github.com/pkozlowski-opensource/ng2-play
-/////
+//
var _ = require('lodash')
var buildConfig = require('./scripts/build/config')
diff --git a/src/components.js b/src/components.js
index 99e4d19a52..6b4d6e891a 100644
--- a/src/components.js
+++ b/src/components.js
@@ -1,7 +1,11 @@
// export all components as array
-import {Aside} from 'ionic2/components/aside/aside';
-
-export let ionicComponents = [
- Aside,
-];
+export * from 'ionic2/components/aside/aside'
+export * from 'ionic2/components/checkbox/checkbox'
+export * from 'ionic2/components/content/content'
+export * from 'ionic2/components/icon/icon'
+export * from 'ionic2/components/item/item'
+export * from 'ionic2/components/list/list'
+export * from 'ionic2/components/nav-view/nav-view'
+export * from 'ionic2/components/toolbar/toolbar'
+export * from 'ionic2/components/view/view'
diff --git a/src/components/aside/aside.js b/src/components/aside/aside.js
index 92b4af05b9..512465efab 100644
--- a/src/components/aside/aside.js
+++ b/src/components/aside/aside.js
@@ -1,6 +1,7 @@
import {Component, Template, Inject, Parent, NgElement} from 'angular2/angular2'
import * as types from 'ionic2/components/aside/extensions/types'
import * as gestures from 'ionic2/components/aside/extensions/gestures';
+import {dom} from 'ionic2/util'
import {IonicComponent} from 'ionic2/config/component'
@Component({
@@ -50,7 +51,7 @@ export class Aside {
if (isOpen !== this.isOpen) {
this.isOpen = isOpen
this.setChanging(true)
- requestAnimationFrame(() => {
+ return dom.rafPromise().then(() => {
this.typeDelegate.setOpen(isOpen)
})
}
diff --git a/src/components/ion.js b/src/components/ion.js
index 3498173d07..45440ad23a 100644
--- a/src/components/ion.js
+++ b/src/components/ion.js
@@ -1,5 +1,3 @@
-import * as util from 'ionic2/util';
-
export class Ion {}
// export class IonElement extends Ion {
diff --git a/src/components/item/extensions/ios.scss b/src/components/item/extensions/ios.scss
index 6030f5c134..69d964ca32 100644
--- a/src/components/item/extensions/ios.scss
+++ b/src/components/item/extensions/ios.scss
@@ -18,7 +18,6 @@ $item-ios-border-color: $list-ios-border-color !default;
.item {
background: $item-ios-background-color;
min-height: $item-ios-min-height;
- padding-left: $item-ios-padding-left;
}
.item-media + .item-content {
@@ -27,7 +26,7 @@ $item-ios-border-color: $list-ios-border-color !default;
.item-content {
min-height: $item-ios-min-height;
- padding: 0;
+ padding: 0 0 0 $item-ios-padding-left;
&:after {
position: absolute;
diff --git a/src/components/item/item-options.js b/src/components/item/item-options.js
new file mode 100644
index 0000000000..b93b73f6f0
--- /dev/null
+++ b/src/components/item/item-options.js
@@ -0,0 +1,13 @@
+
+@Decorator({
+ selector: 'ion-primary-options'
+})
+export class ItemPrimaryOptions {
+}
+
+@Decorator({
+ selector: 'ion-secondary-options'
+})
+export class ItemSecondaryOptions {
+}
+
diff --git a/src/components/item/item-swipe-buttons.js b/src/components/item/item-swipe-buttons.js
new file mode 100644
index 0000000000..605bd1f112
--- /dev/null
+++ b/src/components/item/item-swipe-buttons.js
@@ -0,0 +1,74 @@
+import {Parent, NgElement, Decorator} from 'angular2/angular2'
+import {Item} from 'ionic2/components'
+import {SlideGesture} from 'ionic2/gestures/slide-gesture'
+
+@Decorator({
+ selector: 'ion-primary-swipe-buttons'
+})
+export class ItemPrimarySwipeButtons {
+ constructor(
+ @NgElement() element: NgElement,
+ @Parent() item: Item
+ ) {
+ this.domElement = element.domElement
+ this.parentItem = item
+ this.gesture = new ItemSlideGesture(this)
+ this.gesture.listen()
+
+ this.domElement.addEventListener('transitionend', () => {
+ this.domElement.classList.remove('changing')
+ })
+ }
+
+ setOpen(isOpen) {
+ if (isOpen !== this.isOpen) {
+ this.isOpen = isOpen
+ requestAnimationFrame(() => {
+ this.domElement.classList[isOpen?'add':'remove'](isOpen)
+ })
+ }
+ }
+}
+
+@Decorator({
+ selector: 'ion-secondary-swipe-buttons'
+})
+export class ItemSecondarySwipeButtons {
+}
+
+class ItemSlideGesture extends SlideGesture {
+ constructor(buttons) {
+ super(buttons.parentItem.domElement)
+ this.buttons = buttons
+ }
+
+ getSlideBoundaries() {
+ return {
+ min: -this.buttons.domElement.offsetWidth,
+ max: 0,
+ };
+ }
+
+ getElementStartPos(slide, ev) {
+ return this.buttons.isOpen ? slide.max : slide.min;
+ }
+
+ onSlideBeforeStart() {
+ this.buttons.domElement.classList.add('changing')
+ this.buttons.domElement.classList.add('no-transition')
+ return new Promise(resolve => {
+ requestAnimationFrame(resolve)
+ })
+ }
+ onSlide(slide, ev) {
+ this.buttons.domElement.style.transform = 'translate3d(' + slide.distance + 'px,0,0)';
+ }
+ onSlideEnd(slide, ev) {
+ this.buttons.domElement.style.transform = ''
+ this.buttons.domElement.classList.remove('no-transition')
+ if (Math.abs(ev.velocityX) > 0.2 || Math.abs(slide.delta) > Math.abs(slide.max) * 0.5) {
+ this.buttons.setOpen(!this.buttons.isOpen);
+ }
+ }
+
+}
diff --git a/src/components/item/item.js b/src/components/item/item.js
index 7c8e662da7..f2e40cbec9 100644
--- a/src/components/item/item.js
+++ b/src/components/item/item.js
@@ -1,22 +1,44 @@
import {NgElement, Component, Template} from 'angular2/angular2'
import {IonicComponent} from 'ionic2/config/component'
+import {
+ ItemPrimaryOptions, ItemSecondaryOptions
+} from 'ionic2/components/item/item-options'
+import {
+ ItemPrimarySwipeButtons, ItemSecondarySwipeButtons
+} from 'ionic2/components/item/item-swipe-buttons'
@Component({
selector: 'ion-item'
})
@Template({
- inline: `
`
+ inline: `
+
+
+
+
+
+ `,
+ direcetives: [
+ ItemPrimarySwipeButtons,
+ ItemSecondarySwipeButtons,
+ ItemPrimaryOptions,
+ ItemSecondaryOptions
+ ]
})
export class Item {
- constructor(@NgElement() ele:NgElement) {
+ constructor(
+ @NgElement() ele:NgElement
+ ) {
+ this.domElement = ele.domElement
Item.config.invoke(this)
}
}
diff --git a/src/components/item/item.scss b/src/components/item/item.scss
index 87a3db4bee..f70e7e46eb 100644
--- a/src/components/item/item.scss
+++ b/src/components/item/item.scss
@@ -17,7 +17,32 @@ $item-min-height: 44px !default;
padding: 0;
}
+ion-primary-swipe-buttons,
.item-content {
+ transition: transform 0.3s;
+}
+
+ion-primary-swipe-buttons {
+ position: absolute;
+ top: 0;
+ left: 0;
+ bottom: 0;
+ z-index: 100;
+ transform: translate3d(-100%,0,0);
+
+ &:not(.open):not(.changing) {
+ display: none;
+ }
+ &.open {
+ transform: translate3d(100%, 0, 0);
+ }
+}
+
+.item-content {
+ // TODO add proper bg to cover up swipe buttons
+ background: white;
+ transform: translate3d(0,0,0);
+
position: relative;
@include flex-display();
@@ -36,6 +61,7 @@ $item-min-height: 44px !default;
@include flex-shrink(0);
@include flex-wrap(nowrap);
@include flex-align-items(center);
+ @include flex-order(1);
min-height: $item-min-height;
@@ -47,6 +73,7 @@ $item-min-height: 44px !default;
@include flex(1);
@include flex-shrink(1);
+ @include flex-order(2);
max-width: 100%;
@@ -58,6 +85,7 @@ $item-min-height: 44px !default;
.item-accessory {
@include flex-display();
@include flex-shrink(0);
+ @include flex-order(3);
margin-left: 5px;
max-height: 28px;
diff --git a/src/components/item/test/basic/main.html b/src/components/item/test/basic/main.html
index b41ace4001..ed586961bc 100644
--- a/src/components/item/test/basic/main.html
+++ b/src/components/item/test/basic/main.html
@@ -1,65 +1,19 @@
-
+
+
+
+ List Header
+
-
-
-
- iOS List/Item Default CSS Tests
-
-
-
-
-
+
+
diff --git a/src/components/item/test/basic/main.js b/src/components/item/test/basic/main.js
index e69de29bb2..7337888590 100644
--- a/src/components/item/test/basic/main.js
+++ b/src/components/item/test/basic/main.js
@@ -0,0 +1,21 @@
+import {bootstrap} from 'angular2/core'
+import {Component, Template, For} from 'angular2/angular2'
+import {Item, View, List} from 'ionic2/components'
+
+import {ItemPrimarySwipeButtons} from 'ionic2/components/item/item-swipe-buttons'
+
+@Component({
+ selector: '[ion-app]'
+})
+@Template({
+ url: 'main.html',
+ directives: [Item, View, List, For, ItemPrimarySwipeButtons]
+})
+class App{
+ constructor() {
+ this.items = [1, 2, 3, 4, 5]
+ }
+}
+
+bootstrap(App)
+
diff --git a/src/util.js b/src/util.js
index c0ff70d90d..a7edf761db 100644
--- a/src/util.js
+++ b/src/util.js
@@ -1,82 +1,4 @@
-export function noop() {}
+import * as domUtil from 'ionic2/util/dom'
+export const dom = domUtil
-export function clamp(min, n, max) {
- return Math.max(min, Math.min(n, max));
-}
-
-export function extend(dest) {
- for (var i = 1, ii = arguments.length; i < ii; i++) {
- var source = arguments[i] || {};
- for (var key in source) {
- if (source.hasOwnProperty(key)) {
- dest[key] = source[key];
- }
- }
- }
- return dest;
-}
-
-export function defaults(dest) {
- for (let i = arguments.length - 1; i >= 1; i--) {
- let source = arguments[i] || {};
- for (let key in source) {
- if (source.hasOwnProperty(key) && !dest.hasOwnProperty(key)) {
- dest[key] = source[key];
- }
- }
- }
- return dest;
-}
-
-export const isString = val => typeof val === 'string'
-export const isFunction = val => typeof val === 'function'
-export const isDefined = val => typeof val === 'undefined'
-export const isObject = val => typeof val === 'object'
-export const isArray = Array.isArray
-
-export function pascalCaseToDashCase(str = '') {
- return str.charAt(0).toLowerCase() + str.substring(1).replace(/[A-Z]/g, match => {
- return '-' + match.toLowerCase()
- })
-}
-
-export let array = {
- unique(array) {
- return array.filter((value, index) => {
- return array.indexOf(value) === index
- })
- }
-}
-
-export class Log {
- static log(...args) {
- console.log.apply(console, args)
- }
- static info(...args) {
- console.info.apply(console, args)
- }
- static dir(...args) {
- console.dir.apply(console, args)
- }
- static warn(...args) {
- console.warn.apply(console, args)
- }
- static error(...args) {
- console.error.apply(console, args)
- }
-}
-
-export function readQueryParams() {
- var queryParams = {}
- const startIndex = window.location.href.indexOf('?')
- if (startIndex !== -1) {
- const queries = window.location.href.slice(startIndex + 1).split('&')
- if (queries.length) {
- queries.forEach((param) => {
- var split = param.split('=')
- queryParams[split[0]] = split[1]
- })
- }
- }
- return queryParams
-}
+export * from 'ionic2/util/util'
diff --git a/src/util/dom.js b/src/util/dom.js
new file mode 100644
index 0000000000..06fee40e12
--- /dev/null
+++ b/src/util/dom.js
@@ -0,0 +1,33 @@
+
+const nativeRaf= window.requestAnimationFrame ||
+ window.webkitRequestAnimationFrame ||
+ window.mozRequestAnimationFrame
+const nativeCancelRaf = window.cancelAnimationFrame ||
+ window.webkitCancelAnimationFrame ||
+ window.webkitCancelRequestAnimationFrame
+
+export const raf = nativeRaf || function(callback) {
+ return window.setTimeout(callback, 16.6667)
+}
+export const rafCancel = nativeRaf ? nativeCancelRaf : function(id) {
+ return window.cancelTimeout(id)
+}
+
+export function rafPromise() {
+ return new Promise(resolve => raf(resolve))
+}
+
+
+// We only need to test for webkit in our supported browsers. Webkit is the only browser still
+// using prefixes.
+// Code adapted from angular-animate.js
+export let css = {}
+if (window.ontransitionend === undefined && window.onwebkittransitionend !== undefined) {
+ css.prefix = 'webkit'
+ css.transition = 'webkitTransition'
+ css.transitionEnd = 'webkitTransitionEnd transitionend'
+} else {
+ css.prefix = ''
+ css.transition = 'transition'
+ css.transitionEnd = 'tranistionend'
+}
diff --git a/src/util-test.spec.js b/src/util/test/util.spec.js
similarity index 100%
rename from src/util-test.spec.js
rename to src/util/test/util.spec.js
diff --git a/src/util/util.js b/src/util/util.js
new file mode 100644
index 0000000000..e236709ae3
--- /dev/null
+++ b/src/util/util.js
@@ -0,0 +1,71 @@
+export function noop() {}
+
+export function clamp(min, n, max) {
+ return Math.max(min, Math.min(n, max));
+}
+
+export function extend(dest) {
+ for (var i = 1, ii = arguments.length; i < ii; i++) {
+ var source = arguments[i] || {};
+ for (var key in source) {
+ if (source.hasOwnProperty(key)) {
+ dest[key] = source[key];
+ }
+ }
+ }
+ return dest;
+}
+
+export function defaults(dest) {
+ for (let i = arguments.length - 1; i >= 1; i--) {
+ let source = arguments[i] || {};
+ for (let key in source) {
+ if (source.hasOwnProperty(key) && !dest.hasOwnProperty(key)) {
+ dest[key] = source[key];
+ }
+ }
+ }
+ return dest;
+}
+
+export const isString = val => typeof val === 'string'
+export const isFunction = val => typeof val === 'function'
+export const isDefined = val => typeof val === 'undefined'
+export const isObject = val => typeof val === 'object'
+export const isArray = Array.isArray
+
+export function pascalCaseToDashCase(str = '') {
+ return str.charAt(0).toLowerCase() + str.substring(1).replace(/[A-Z]/g, match => {
+ return '-' + match.toLowerCase()
+ })
+}
+
+export class Log {
+ static log(...args) {
+ console.log.apply(console, args)
+ }
+ static info(...args) {
+ console.info.apply(console, args)
+ }
+ static warn(...args) {
+ console.warn.apply(console, args)
+ }
+ static error(...args) {
+ console.error.apply(console, args)
+ }
+}
+
+export function readQueryParams() {
+ var queryParams = {}
+ const startIndex = window.location.href.indexOf('?')
+ if (startIndex !== -1) {
+ const queries = window.location.href.slice(startIndex + 1).split('&')
+ if (queries.length) {
+ queries.forEach((param) => {
+ var split = param.split('=')
+ queryParams[split[0]] = split[1]
+ })
+ }
+ }
+ return queryParams
+}