fix(sliding-item): finish it

This commit is contained in:
Manu Mtz.-Almeida
2017-11-02 10:25:40 +01:00
parent d0e486d2d8
commit 1bfc0c71e3
13 changed files with 269 additions and 325 deletions

View File

@ -1222,6 +1222,7 @@ declare global {
isRightSide?: any, isRightSide?: any,
width?: any, width?: any,
fireSwipeEvent?: any,
side?: string side?: string
} }
} }
@ -1252,7 +1253,10 @@ declare global {
mode?: string, mode?: string,
color?: string, color?: string,
close?: any getOpenAmount?: any,
getSlidingPercent?: any,
close?: any,
closeOpened?: any
} }
} }
} }

View File

@ -1,6 +1,4 @@
import { Component, Prop } from '@stencil/core'; import { Component, Prop } from '@stencil/core';
import { createThemedClasses } from '../../utils/theme';
/** /**
* @name ItemOption * @name ItemOption
@ -10,7 +8,10 @@ import { createThemedClasses } from '../../utils/theme';
* action for the item. * action for the item.
*/ */
@Component({ @Component({
tag: 'ion-item-option' tag: 'ion-item-option',
host: {
theme: 'item-option'
}
}) })
export class ItemOption { export class ItemOption {
mode: string; mode: string;
@ -35,18 +36,14 @@ export class ItemOption {
} }
protected render() { protected render() {
const themedClasses = createThemedClasses(this.mode, this.color, 'item-option-button');
const TagType = this.href ? 'a' : 'button'; const TagType = this.href ? 'a' : 'button';
return [
return ( <TagType class='item-option-button' onClick={this.clickedOptionButton.bind(this)} disabled={this.disabled}></TagType>,
<TagType class={themedClasses} onClick={this.clickedOptionButton.bind(this)} disabled={this.disabled}> <span class='button-inner'>
<span class='button-inner'> <slot></slot>
<slot></slot> </span>
</span> ];
<div class='button-effect'></div>
</TagType>
);
} }
} }

View File

@ -40,15 +40,21 @@ export class ItemOptions {
*/ */
@Event() ionSwipe: EventEmitter; @Event() ionSwipe: EventEmitter;
@Method() isRightSide() { @Method()
const isRTL = document.dir === 'rtl'; isRightSide() {
return isRightSide(this.side, isRTL, true); return isRightSide(this.side, true);
} }
@Method() width(): number { @Method()
width(): number {
return this.el.offsetWidth; return this.el.offsetWidth;
} }
@Method()
fireSwipeEvent(value: any) {
this.ionSwipe.emit(value);
}
protected render() { protected render() {
return <slot></slot>; return <slot></slot>;
} }

View File

@ -29,13 +29,13 @@ $item-ios-sliding-button-icon-color: color-contrast($colors-ios, $item-i
border-bottom: $hairlines-width solid $list-ios-border-color; border-bottom: $hairlines-width solid $list-ios-border-color;
} }
.item-option-button-ios { .item-option-ios {
font-size: $item-ios-sliding-button-font-size; font-size: $item-ios-sliding-button-font-size;
color: $item-ios-sliding-button-text-color; color: $item-ios-sliding-button-text-color;
background-color: $item-ios-sliding-button-background-color; background-color: $item-ios-sliding-button-background-color;
} }
.item-option-button-ios .icon { .item-option-ios .icon {
fill: $item-ios-sliding-button-icon-color; fill: $item-ios-sliding-button-icon-color;
} }
@ -53,12 +53,12 @@ $item-ios-sliding-button-icon-color: color-contrast($colors-ios, $item-i
@each $color-name, $color-base, $color-contrast in get-colors($colors-ios) { @each $color-name, $color-base, $color-contrast in get-colors($colors-ios) {
.item-option-button-ios-#{$color-name} { .item-option-ios-#{$color-name} {
color: $color-contrast; color: $color-contrast;
background-color: $color-base; background-color: $color-base;
} }
.item-option-button-ios-#{$color-name} .icon { .item-option-ios-#{$color-name} .icon {
fill: $color-contrast; fill: $color-contrast;
} }

View File

@ -29,13 +29,13 @@ $item-md-sliding-button-icon-color: color-contrast($colors-md, $item-md
border-bottom: 1px solid $list-md-border-color; border-bottom: 1px solid $list-md-border-color;
} }
.item-option-button-md { .item-option-md {
font-size: $item-md-sliding-button-font-size; font-size: $item-md-sliding-button-font-size;
color: $item-md-sliding-button-text-color; color: $item-md-sliding-button-text-color;
background-color: $item-md-sliding-button-background-color; background-color: $item-md-sliding-button-background-color;
} }
.item-option-button-md .icon { .item-option-md .icon {
fill: $item-md-sliding-button-icon-color; fill: $item-md-sliding-button-icon-color;
} }
@ -52,12 +52,12 @@ $item-md-sliding-button-icon-color: color-contrast($colors-md, $item-md
@each $color-name, $color-base, $color-contrast in get-colors($colors-md) { @each $color-name, $color-base, $color-contrast in get-colors($colors-md) {
.item-option-button-md-#{$color-name} { .item-option-md-#{$color-name} {
color: $color-contrast; color: $color-contrast;
background-color: $color-base; background-color: $color-base;
} }
.item-option-button-md-#{$color-name} .icon { .item-option-md-#{$color-name} .icon {
fill: $color-contrast; fill: $color-contrast;
} }

View File

@ -2,7 +2,7 @@
// Item Sliding // Item Sliding
// -------------------------------------------------- // --------------------------------------------------
// The hidden buttons that can be exposed under a list item by dragging // The hidden right-side buttons that can be exposed under a list item with dragging.
ion-item-sliding { ion-item-sliding {
position: relative; position: relative;
@ -12,10 +12,6 @@ ion-item-sliding {
width: 100%; width: 100%;
} }
ion-item-sliding ion-item {
position: static;
}
ion-item-options { ion-item-options {
position: absolute; position: absolute;
z-index: $z-index-item-options; z-index: $z-index-item-options;
@ -66,29 +62,31 @@ ion-item-options[side=left] {
} }
} }
.item-option-button {
@include margin(0);
@include border-radius(0);
ion-item-option {
@include padding(0, .7em); @include padding(0, .7em);
display: inline-flex; position: relative;
display: flex;
align-items: center; align-items: center;
height: 100%; min-width: 6rem;
}
.item-option-button {
@include position(0, 0, 0, 0);
@include margin(0);
@include padding(0);
@include border-radius(0);
position: absolute;
border: 0; border: 0;
box-shadow: none; background: none;
box-sizing: border-box;
} }
.item-option-button::before { ion-item-options:not([icon-start]) ion-item-option:not([icon-only]) {
@include margin(0, auto);
}
ion-item-options:not([icon-start]) .item-option-button:not([icon-only]) {
.button-inner { .button-inner {
flex-direction: column; flex-direction: column;
} }
@ -131,7 +129,7 @@ ion-item-sliding.active-slide {
// Item Expandable Animation // Item Expandable Animation
// -------------------------------------------------- // --------------------------------------------------
ion-item-option[expandable] .item-option-button { ion-item-option[expandable] {
flex-shrink: 0; flex-shrink: 0;
transition-duration: 0; transition-duration: 0;
@ -139,7 +137,7 @@ ion-item-option[expandable] .item-option-button {
transition-timing-function: cubic-bezier(.65, .05, .36, 1); transition-timing-function: cubic-bezier(.65, .05, .36, 1);
} }
ion-item-sliding.active-swipe-right ion-item-option[expandable] .item-option-button { ion-item-sliding.active-swipe-right ion-item-option[expandable] {
transition-duration: .6s; transition-duration: .6s;
transition-property: padding-left; transition-property: padding-left;
@ -157,7 +155,7 @@ ion-item-sliding.active-swipe-right ion-item-option[expandable] .item-option-but
} }
} }
ion-item-sliding.active-swipe-left ion-item-option[expandable] .item-option-button { ion-item-sliding.active-swipe-left ion-item-option[expandable] {
transition-duration: .6s; transition-duration: .6s;
transition-property: padding-right; transition-property: padding-right;

View File

@ -8,11 +8,12 @@ import { ItemOptions } from './item-options';
const SWIPE_MARGIN = 30; const SWIPE_MARGIN = 30;
const ELASTIC_FACTOR = 0.55; const ELASTIC_FACTOR = 0.55;
const ITEM_SIDE_FLAG_NONE = 0; const enum ItemSide {
const ITEM_SIDE_FLAG_LEFT = 1 << 0; None = 0,
const ITEM_SIDE_FLAG_RIGHT = 1 << 1; Left = 1 << 0,
const ITEM_SIDE_FLAG_BOTH = ITEM_SIDE_FLAG_LEFT | ITEM_SIDE_FLAG_RIGHT; Right = 1 << 1,
Both = Left | Right
}
const enum SlidingState { const enum SlidingState {
Disabled = 1 << 1, Disabled = 1 << 1,
@ -135,30 +136,23 @@ const enum SlidingState {
} }
}) })
export class ItemSliding { export class ItemSliding {
@Element() private el: HTMLElement;
private item: HTMLIonItemElement; private item: HTMLIonItemElement;
private list: HTMLIonListElement; private list: HTMLIonListElement;
private openAmount = 0;
private openAmount: number = 0; private initialOpenAmount = 0;
private startX: number = 0; private optsWidthRightSide = 0;
private optsWidthRightSide: number = 0; private optsWidthLeftSide = 0;
private optsWidthLeftSide: number = 0; private sides: ItemSide;
private sides: number;
private tmr: any = null; private tmr: any = null;
private leftOptions: ItemOptions; private leftOptions: ItemOptions;
private rightOptions: ItemOptions; private rightOptions: ItemOptions;
private optsDirty: boolean = true; private optsDirty: boolean = true;
private gestureOptions: any;
@Element() private el: HTMLElement;
@State() state: SlidingState = SlidingState.Disabled; @State() state: SlidingState = SlidingState.Disabled;
private preSelectedContainer: ItemSliding = null;
private selectedContainer: ItemSliding = null;
openContainer: ItemSliding = null;
private firstCoordX: number;
private firstTimestamp: number;
/** /**
* @output {event} Emitted when the sliding position changes. * @output {event} Emitted when the sliding position changes.
@ -183,92 +177,39 @@ export class ItemSliding {
*/ */
@Event() ionDrag: EventEmitter; @Event() ionDrag: EventEmitter;
constructor() {
this.gestureOptions = {
'canStart': this.canStart.bind(this),
'onStart': this.onDragStart.bind(this),
'onMove': this.onDragMove.bind(this),
'onEnd': this.onDragEnd.bind(this),
'gestureName': 'item-swipe',
'gesturePriority': -10,
'type': 'pan',
'direction': 'x',
'maxAngle': 20,
'threshold': 5,
'attachTo': 'parent'
};
}
protected ionViewDidLoad() { protected ionViewDidLoad() {
const options = this.el.querySelectorAll('ion-item-options');
let sides = 0;
// Reset left and right options in case they were removed
this.leftOptions = this.rightOptions = null;
for (var i = 0; i < options.length; i++) {
let option = options[i];
if (option.isRightSide()) {
this.rightOptions = option;
sides |= ITEM_SIDE_FLAG_RIGHT;
} else {
this.leftOptions = option;
sides |= ITEM_SIDE_FLAG_LEFT;
}
}
this.optsDirty = true;
this.sides = sides;
this.item = this.el.querySelector('ion-item'); this.item = this.el.querySelector('ion-item');
// Get the parent list to close open containers
this.list = this.el.closest('ion-list') as HTMLIonListElement; this.list = this.el.closest('ion-list') as HTMLIonListElement;
this.updateOptions();
} }
canStart(gesture: GestureDetail): boolean { protected ionViewDidUnLoad() {
if (this.selectedContainer) { this.item = this.list = this.leftOptions = this.rightOptions = null;
return false;
}
// Get swiped sliding container
let container = this;
// Close open container if it is not the selected one.
if (this.list && container !== this.list.getOpenedItem()) {
this.closeOpened();
}
this.preSelectedContainer = container;
this.firstCoordX = gesture.currentX;
this.firstTimestamp = Date.now();
return true;
} }
onDragStart(gesture: GestureDetail) { @Method()
this.selectedContainer = this.preSelectedContainer;
this.list.setOpenedItem(this.selectedContainer);
this.selectedContainer.startSliding(gesture.currentX);
}
onDragMove(gesture: GestureDetail) {
this.selectedContainer && this.selectedContainer.moveSliding(gesture.currentX);
}
onDragEnd(gesture: GestureDetail) {
let coordX = gesture.currentX;
let deltaX = (coordX - this.firstCoordX);
let deltaT = (Date.now() - this.firstTimestamp);
this.selectedContainer.endSliding(deltaX / deltaT);
this.selectedContainer = null;
this.preSelectedContainer = null;
}
closeOpened(): boolean {
this.selectedContainer = null;
if (this.list.getOpenedItem()) {
this.list.closeSlidingItems();
return true;
}
return false;
}
/**
* @hidden
*/
getOpenAmount(): number { getOpenAmount(): number {
return this.openAmount; return this.openAmount;
} }
/** @Method()
* @hidden
*/
getSlidingPercent(): number { getSlidingPercent(): number {
const openAmount = this.openAmount; const openAmount = this.openAmount;
if (openAmount > 0) { if (openAmount > 0) {
@ -280,156 +221,6 @@ export class ItemSliding {
} }
} }
/**
* @hidden
*/
startSliding(startX: number) {
if (this.tmr) {
clearTimeout(this.tmr);
this.tmr = null;
}
if (this.openAmount === 0) {
this.optsDirty = true;
this.setState(SlidingState.Enabled);
}
this.startX = startX + this.openAmount;
this.item.style.transition = 'none';
}
/**
* @hidden
*/
moveSliding(x: number): number {
if (this.optsDirty) {
this.calculateOptsWidth();
return 0;
}
let openAmount = (this.startX - x);
switch (this.sides) {
case ITEM_SIDE_FLAG_RIGHT: openAmount = Math.max(0, openAmount); break;
case ITEM_SIDE_FLAG_LEFT: openAmount = Math.min(0, openAmount); break;
case ITEM_SIDE_FLAG_BOTH: break;
case ITEM_SIDE_FLAG_NONE: return 0;
default: console.warn('invalid ItemSideFlags value', this.sides); break;
}
let optsWidth;
if (openAmount > this.optsWidthRightSide) {
optsWidth = this.optsWidthRightSide;
openAmount = optsWidth + (openAmount - optsWidth) * ELASTIC_FACTOR;
} else if (openAmount < -this.optsWidthLeftSide) {
optsWidth = -this.optsWidthLeftSide;
openAmount = optsWidth + (openAmount - optsWidth) * ELASTIC_FACTOR;
}
this.setOpenAmount(openAmount, false);
return openAmount;
}
/**
* @hidden
*/
endSliding(velocity: number): number {
let restingPoint = (this.openAmount > 0)
? this.optsWidthRightSide
: -this.optsWidthLeftSide;
// Check if the drag didn't clear the buttons mid-point
// and we aren't moving fast enough to swipe open
const isResetDirection = (this.openAmount > 0) === !(velocity < 0);
const isMovingFast = Math.abs(velocity) > 0.3;
const isOnCloseZone = Math.abs(this.openAmount) < Math.abs(restingPoint / 2);
if (swipeShouldReset(isResetDirection, isMovingFast, isOnCloseZone)) {
restingPoint = 0;
}
this.setOpenAmount(restingPoint, true);
this.fireSwipeEvent();
return restingPoint;
}
/**
* @hidden
* Emit the ionSwipe event on the child options
*/
fireSwipeEvent() {
if (this.state & SlidingState.SwipeRight) {
this.rightOptions.ionSwipe.emit(this);
} else if (this.state & SlidingState.SwipeLeft) {
this.leftOptions.ionSwipe.emit(this);
}
}
/**
* @hidden
*/
calculateOptsWidth() {
if (!this.optsDirty) {
return;
}
this.optsWidthRightSide = 0;
if (this.rightOptions) {
this.optsWidthRightSide = this.rightOptions.width();
this.optsWidthRightSide === 0 && console.warn('optsWidthRightSide should not be zero');
}
this.optsWidthLeftSide = 0;
if (this.leftOptions) {
this.optsWidthLeftSide = this.leftOptions.width();
this.optsWidthLeftSide === 0 && console.warn('optsWidthLeftSide should not be zero');
}
this.optsDirty = false;
}
setOpenAmount(openAmount: number, isFinal: boolean) {
if (this.tmr) {
clearTimeout(this.tmr);
this.tmr = null;
}
this.openAmount = openAmount;
if (isFinal) {
this.item.style.transition = '';
} else {
var state;
if (openAmount > 0) {
state = (openAmount >= (this.optsWidthRightSide + SWIPE_MARGIN))
? SlidingState.Right | SlidingState.SwipeRight
: SlidingState.Right;
this.setState(state);
} else if (openAmount < 0) {
state = (openAmount <= (-this.optsWidthLeftSide - SWIPE_MARGIN))
? SlidingState.Left | SlidingState.SwipeLeft
: SlidingState.Left;
this.setState(state);
}
}
if (openAmount === 0) {
this.tmr = setTimeout(() => {
this.setState(SlidingState.Disabled);
this.tmr = null;
}, 600);
this.item.style.transform = '';
return;
}
this.item.style.transform = `translate3d(${-openAmount}px,0,0)`;
this.ionDrag.emit();
}
private setState(state: SlidingState) {
if (state === this.state) {
return;
}
this.state = state;
}
/** /**
* Close the sliding item. Items can also be closed from the [List](../../list/List). * Close the sliding item. Items can also be closed from the [List](../../list/List).
@ -470,7 +261,160 @@ export class ItemSliding {
this.setOpenAmount(0, true); this.setOpenAmount(0, true);
} }
hostData() { @Method()
closeOpened(): boolean {
return this.list && this.list.closeSlidingItems();
}
private updateOptions() {
const options = this.el.querySelectorAll('ion-item-options');
let sides = 0;
// Reset left and right options in case they were removed
this.leftOptions = this.rightOptions = null;
for (var i = 0; i < options.length; i++) {
let option = options.item(i);
if (option.isRightSide()) {
this.rightOptions = option;
sides |= ItemSide.Right;
} else {
this.leftOptions = option;
sides |= ItemSide.Left;
}
}
this.optsDirty = true;
this.sides = sides;
}
private canStart(): boolean {
const selected = this.list && this.list.getOpenedItem();
if (selected && selected !== this) {
this.closeOpened();
return false;
}
return true;
}
private onDragStart() {
this.list && this.list.setOpenedItem(this);
if (this.tmr) {
clearTimeout(this.tmr);
this.tmr = null;
}
if (this.openAmount === 0) {
this.optsDirty = true;
this.state = SlidingState.Enabled;
}
this.initialOpenAmount = this.openAmount;
this.item.style.transition = 'none';
}
private onDragMove(gesture: GestureDetail) {
if (this.optsDirty) {
this.calculateOptsWidth();
}
let openAmount = this.initialOpenAmount - gesture.deltaX;
switch (this.sides) {
case ItemSide.Right: openAmount = Math.max(0, openAmount); break;
case ItemSide.Left: openAmount = Math.min(0, openAmount); break;
case ItemSide.Both: break;
case ItemSide.None: return;
default: console.warn('invalid ItemSideFlags value', this.sides); break;
}
let optsWidth;
if (openAmount > this.optsWidthRightSide) {
optsWidth = this.optsWidthRightSide;
openAmount = optsWidth + (openAmount - optsWidth) * ELASTIC_FACTOR;
} else if (openAmount < -this.optsWidthLeftSide) {
optsWidth = -this.optsWidthLeftSide;
openAmount = optsWidth + (openAmount - optsWidth) * ELASTIC_FACTOR;
}
this.setOpenAmount(openAmount, false);
}
private onDragEnd(gesture: GestureDetail) {
const velocity = gesture.velocityX;
let restingPoint = (this.openAmount > 0)
? this.optsWidthRightSide
: -this.optsWidthLeftSide;
// Check if the drag didn't clear the buttons mid-point
// and we aren't moving fast enough to swipe open
const isResetDirection = (this.openAmount > 0) === !(velocity < 0);
const isMovingFast = Math.abs(velocity) > 0.3;
const isOnCloseZone = Math.abs(this.openAmount) < Math.abs(restingPoint / 2);
if (swipeShouldReset(isResetDirection, isMovingFast, isOnCloseZone)) {
restingPoint = 0;
}
this.setOpenAmount(restingPoint, true);
if (this.state & SlidingState.SwipeRight) {
this.rightOptions.fireSwipeEvent(this);
} else if (this.state & SlidingState.SwipeLeft) {
this.leftOptions.fireSwipeEvent(this);
}
}
private calculateOptsWidth() {
this.optsWidthRightSide = 0;
if (this.rightOptions) {
this.optsWidthRightSide = this.rightOptions.width();
}
this.optsWidthLeftSide = 0;
if (this.leftOptions) {
this.optsWidthLeftSide = this.leftOptions.width();
}
this.optsDirty = false;
}
private setOpenAmount(openAmount: number, isFinal: boolean) {
if (this.tmr) {
clearTimeout(this.tmr);
this.tmr = null;
}
const style = this.item.style;
this.openAmount = openAmount;
if (isFinal) {
style.transition = '';
} else if (openAmount > 0) {
this.state = (openAmount >= (this.optsWidthRightSide + SWIPE_MARGIN))
? SlidingState.Right | SlidingState.SwipeRight
: SlidingState.Right;
} else if (openAmount < 0) {
this.state = (openAmount <= (-this.optsWidthLeftSide - SWIPE_MARGIN))
? SlidingState.Left | SlidingState.SwipeLeft
: SlidingState.Left;
}
if (openAmount === 0) {
this.tmr = setTimeout(() => {
this.state = SlidingState.Disabled;
this.tmr = null;
}, 600);
this.list && this.list.setOpenedItem(null);
style.transform = '';
return;
}
style.transform = `translate3d(${-openAmount}px,0,0)`;
this.ionDrag.emit(this);
}
protected hostData() {
return { return {
class: { class: {
'item-wrapper': true, 'item-wrapper': true,
@ -485,19 +429,7 @@ export class ItemSliding {
protected render() { protected render() {
return ( return (
<ion-gesture {...{ <ion-gesture {...this.gestureOptions}>
'canStart': this.canStart.bind(this),
'onStart': this.onDragStart.bind(this),
'onMove': this.onDragMove.bind(this),
'onEnd': this.onDragEnd.bind(this),
'gestureName': 'item-swipe',
'gesturePriority': -10,
'type': 'pan',
'direction': 'x',
'maxAngle': 20,
'threshold': 5,
'attachTo': 'parent'
}}>
<slot></slot> <slot></slot>
</ion-gesture> </ion-gesture>
); );

View File

@ -29,13 +29,13 @@ $item-wp-sliding-button-icon-color: color-contrast($colors-wp, $item-wp
border-bottom: 1px solid $list-wp-border-color; border-bottom: 1px solid $list-wp-border-color;
} }
.item-option-button-wp { .item-option-wp {
font-size: $item-wp-sliding-button-font-size; font-size: $item-wp-sliding-button-font-size;
color: $item-wp-sliding-button-text-color; color: $item-wp-sliding-button-text-color;
background-color: $item-wp-sliding-button-background-color; background-color: $item-wp-sliding-button-background-color;
} }
.item-option-button-wp .icon { .item-option-wp .icon {
fill: $item-wp-sliding-button-icon-color; fill: $item-wp-sliding-button-icon-color;
} }
@ -52,12 +52,12 @@ $item-wp-sliding-button-icon-color: color-contrast($colors-wp, $item-wp
@each $color-name, $color-base, $color-contrast in get-colors($colors-wp) { @each $color-name, $color-base, $color-contrast in get-colors($colors-wp) {
.item-option-button-wp-#{$color-name} { item-option-wp-#{$color-name} {
color: $color-contrast; color: $color-contrast;
background-color: $color-base; background-color: $color-base;
} }
.item-option-button-wp-#{$color-name} .icon { item-option-wp-#{$color-name} .icon {
fill: $color-contrast; fill: $color-contrast;
} }

View File

@ -143,13 +143,13 @@
<p>I think I figured out how to get more Mountain Dew</p> <p>I think I figured out how to get more Mountain Dew</p>
</ion-label> </ion-label>
</ion-item> </ion-item>
<ion-item-options side="left" (ionSwipe)="unread($event)" class="sliding-enabled"> <ion-item-options side="left" class="sliding-enabled">
<ion-item-option color="secondary" expandable onclick="unread('item2')"> <ion-item-option color="secondary" expandable onclick="unread('item2')">
<ion-icon name="ios-checkmark"></ion-icon>Unread <ion-icon name="ios-checkmark"></ion-icon>Unread
</ion-item-option> </ion-item-option>
</ion-item-options> </ion-item-options>
<ion-item-options side="right" (ionSwipe)="del('item2')" class="sliding-enabled"> <ion-item-options side="right" class="sliding-enabled">
<ion-item-option color="primary" onclick="archive('item2')"> <ion-item-option color="primary" onclick="archive('item2')">
<ion-icon name="mail"></ion-icon>Archive <ion-icon name="mail"></ion-icon>Archive
</ion-item-option> </ion-item-option>
@ -166,13 +166,13 @@
<p>I think I figured out how to get more Mountain Dew</p> <p>I think I figured out how to get more Mountain Dew</p>
</ion-label> </ion-label>
</ion-item> </ion-item>
<ion-item-options side="left" icon-start (ionSwipe)="unread($event)" class="sliding-enabled"> <ion-item-options side="left" icon-start class="sliding-enabled">
<ion-item-option color="secondary" expandable onclick="unread('item3')"> <ion-item-option color="secondary" expandable onclick="unread('item3')">
<ion-icon name="ios-checkmark"></ion-icon>Unread <ion-icon name="ios-checkmark"></ion-icon>Unread
</ion-item-option> </ion-item-option>
</ion-item-options> </ion-item-options>
<ion-item-options icon-start (ionSwipe)="del('item3')"> <ion-item-options icon-start>
<ion-item-option color="primary" onclick="archive('item3')"> <ion-item-option color="primary" onclick="archive('item3')">
<ion-icon name="mail"></ion-icon>Archive <ion-icon name="mail"></ion-icon>Archive
</ion-item-option> </ion-item-option>
@ -190,7 +190,7 @@
One Line w/ Icon, div only text One Line w/ Icon, div only text
</ion-label> </ion-label>
</ion-item> </ion-item>
<ion-item-options icon-start (ionSwipe)="archive($event)"> <ion-item-options icon-start>
<ion-item-option color="primary" onclick="archive('item4')" expandable class="sliding-enabled"> <ion-item-option color="primary" onclick="archive('item4')" expandable class="sliding-enabled">
<ion-icon name="archive"></ion-icon>Archive <ion-icon name="archive"></ion-icon>Archive
</ion-item-option> </ion-item-option>
@ -249,7 +249,7 @@
<p>Paragraph text.</p> <p>Paragraph text.</p>
</ion-label> </ion-label>
</ion-item> </ion-item>
<ion-item-options (ionSwipe)="download('item8')"> <ion-item-options>
<ion-item-option color="primary" onclick="archive('item8')"> <ion-item-option color="primary" onclick="archive('item8')">
<ion-icon name="archive"></ion-icon>Archive <ion-icon name="archive"></ion-icon>Archive
</ion-item-option> </ion-item-option>
@ -379,6 +379,9 @@
function reload() { function reload() {
window.location.reload(); window.location.reload();
} }
document.addEventListener('ionSwipe', (ev)=> console.log('SWIPE!!', ev.detail));
document.addEventListener('ionDrag', (ev)=> console.log('DRAG!!', ev.detail.getOpenAmount()));
</script> </script>
<style> <style>
img { img {

View File

@ -28,9 +28,13 @@ export class List {
} }
@Method() @Method()
closeSlidingItems() { closeSlidingItems(): boolean {
this.openedItem && this.openedItem.close(); if (this.openedItem) {
this.openedItem = null; this.openedItem.close();
this.openedItem = null;
return true;
}
return false;
} }
protected render() { protected render() {

View File

@ -85,7 +85,7 @@ export class MenuController {
* time. If there are multiple menus on the same side, then enabling one menu * time. If there are multiple menus on the same side, then enabling one menu
* will also automatically disable all the others that are on the same side. * will also automatically disable all the others that are on the same side.
* @param {string} [menuId] Optionally get the menu by its id, or side. * @param {string} [menuId] Optionally get the menu by its id, or side.
* @return {Menu} Returns the instance of the menu, which is useful for chaining. * @return {HTMLIonMenuElement} Returns the instance of the menu, which is useful for chaining.
*/ */
@Method() @Method()
enable(shouldEnable: boolean, menuId?: string): HTMLIonMenuElement { enable(shouldEnable: boolean, menuId?: string): HTMLIonMenuElement {
@ -100,7 +100,7 @@ export class MenuController {
* Used to enable or disable the ability to swipe open the menu. * Used to enable or disable the ability to swipe open the menu.
* @param {boolean} shouldEnable True if it should be swipe-able, false if not. * @param {boolean} shouldEnable True if it should be swipe-able, false if not.
* @param {string} [menuId] Optionally get the menu by its id, or side. * @param {string} [menuId] Optionally get the menu by its id, or side.
* @return {Menu} Returns the instance of the menu, which is useful for chaining. * @return {HTMLIonMenuElement} Returns the instance of the menu, which is useful for chaining.
*/ */
@Method() @Method()
swipeEnable(shouldEnable: boolean, menuId?: string): HTMLIonMenuElement { swipeEnable(shouldEnable: boolean, menuId?: string): HTMLIonMenuElement {
@ -145,7 +145,7 @@ export class MenuController {
* provided, then it'll try to find the menu using the menu's `id` * provided, then it'll try to find the menu using the menu's `id`
* property. If a menu is not found then it'll return `null`. * property. If a menu is not found then it'll return `null`.
* @param {string} [menuId] Optionally get the menu by its id, or side. * @param {string} [menuId] Optionally get the menu by its id, or side.
* @return {Menu} Returns the instance of the menu if found, otherwise `null`. * @return {HTMLIonMenuElement} Returns the instance of the menu if found, otherwise `null`.
*/ */
@Method() @Method()
get(menuId?: string): HTMLIonMenuElement { get(menuId?: string): HTMLIonMenuElement {
@ -188,7 +188,7 @@ export class MenuController {
} }
/** /**
* @return {Array<Menu>} Returns an array of all menu instances. * @return {Array<HTMLIonMenuElement>} Returns an array of all menu instances.
*/ */
@Method() @Method()
getMenus(): HTMLIonMenuElement[] { getMenus(): HTMLIonMenuElement[] {

View File

@ -82,8 +82,7 @@ export class Menu {
@Prop() side: Side = 'start'; @Prop() side: Side = 'start';
@PropDidChange('side') @PropDidChange('side')
sideChanged() { sideChanged() {
const isRTL = false; this.isRightSide = isRightSide(this.side);
this.isRightSide = isRightSide(this.side, isRTL);
} }
/** /**

View File

@ -175,7 +175,8 @@ export function checkEdgeSide(posX: number, isRightSide: boolean, maxEdgeStart:
* @param isRTL whether the application dir is rtl * @param isRTL whether the application dir is rtl
* @param defaultRight whether the default side is right * @param defaultRight whether the default side is right
*/ */
export function isRightSide(side: Side, isRTL: boolean, defaultRight: boolean = false): boolean { export function isRightSide(side: Side, defaultRight: boolean = false): boolean {
const isRTL = document.dir === 'rtl';
switch (side) { switch (side) {
case 'right': return true; case 'right': return true;
case 'left': return false; case 'left': return false;