fix(ripple-effect): using method invocation instead of events

fixes #15318
This commit is contained in:
Manu Mtz.-Almeida
2018-08-24 22:58:12 +02:00
parent 926758e585
commit 4a45effe8c
16 changed files with 30 additions and 82 deletions

View File

@ -340,7 +340,7 @@ export class InfiniteScroll {
constructor(r: ElementRef) {
const el = r.nativeElement;
proxyMethods(this, el, ['complete', 'waitFor']);
proxyMethods(this, el, ['complete']);
proxyInputs(this, el, ['threshold', 'disabled', 'position']);
proxyOutputs(this, el, ['ionInfinite']);
}
@ -640,13 +640,12 @@ export class ReorderGroup {
}
export declare interface RippleEffect extends Promisify<StencilComponents<'IonRippleEffect'>> {}
@Component({ selector: 'ion-ripple-effect', changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, template: '<ng-content></ng-content>', inputs: ['parent', 'tapClick'] })
@Component({ selector: 'ion-ripple-effect', changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, template: '<ng-content></ng-content>' })
export class RippleEffect {
constructor(r: ElementRef) {
const el = r.nativeElement;
proxyMethods(this, el, ['addRipple']);
proxyInputs(this, el, ['parent', 'tapClick']);
}
}

View File

@ -3517,19 +3517,8 @@ export namespace Components {
* Adds the ripple effect to the parent element
*/
'addRipple': (pageX: number, pageY: number) => void;
'parent': HTMLElement | string;
/**
* If true, the ripple effect will listen to any click events and animate
*/
'tapClick': boolean;
}
interface IonRippleEffectAttributes extends StencilHTMLAttributes {
'parent'?: HTMLElement | string;
/**
* If true, the ripple effect will listen to any click events and animate
*/
'tapClick'?: boolean;
}
interface IonRippleEffectAttributes extends StencilHTMLAttributes {}
interface IonRouteRedirect {
/**

View File

@ -333,7 +333,7 @@ export class Alert implements OverlayInterface {
{i.label}
</div>
</div>
{ this.mode === 'md' && <ion-ripple-effect tapClick={true}/> }
{ this.mode === 'md' && <ion-ripple-effect /> }
</button>
))}
</div>
@ -362,7 +362,7 @@ export class Alert implements OverlayInterface {
{i.label}
</div>
</div>
{ this.mode === 'md' && <ion-ripple-effect tapClick={true}/> }
{ this.mode === 'md' && <ion-ripple-effect /> }
</button>
))}
</div>

View File

@ -83,7 +83,7 @@ export class BackButton {
<span class="back-button-inner">
{ backButtonIcon && <ion-icon icon={backButtonIcon} lazy={false}/> }
{ this.mode === 'ios' && backButtonText && <span class="button-text">{backButtonText}</span> }
{ this.mode === 'md' && <ion-ripple-effect tapClick={true} parent={this.el}/> }
{ this.mode === 'md' && <ion-ripple-effect /> }
</span>
</button>
);

View File

@ -183,7 +183,7 @@ export class Button {
<slot></slot>
<slot name="end"></slot>
</span>
{ this.mode === 'md' && <ion-ripple-effect tapClick={true} parent={this.el} /> }
{ this.mode === 'md' && <ion-ripple-effect /> }
</TagType>
);
}

View File

@ -62,7 +62,7 @@ export class ChipButton {
<span class="chip-button-inner">
<slot></slot>
</span>
{ this.mode === 'md' && <ion-ripple-effect tapClick={true}/> }
{ this.mode === 'md' && <ion-ripple-effect /> }
</TagType>
);
}

View File

@ -537,7 +537,7 @@ export class Datetime {
aria-disabled={this.disabled ? 'true' : null}
onClick={this.open.bind(this)}
class="datetime-cover">
{ this.mode === 'md' && <ion-ripple-effect tapClick={true}/> }
{ this.mode === 'md' && <ion-ripple-effect /> }
</button>
];
}

View File

@ -101,7 +101,7 @@ export class FabButton {
<span class="fab-button-inner">
<slot></slot>
</span>
{ this.mode === 'md' && <ion-ripple-effect tapClick={true} parent={this.el}/> }
{ this.mode === 'md' && <ion-ripple-effect /> }
</TagType>
);
}

View File

@ -36,7 +36,6 @@ Separating the `ion-infinite-scroll` and `ion-infinite-scroll-content` component
| Method | Description |
| ---------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `complete` | Call `complete()` within the `infinite` output event handler when your async operation has completed. For example, the `loading` state is while the app is performing an asynchronous operation, such as receiving more data from an AJAX request to add more items to a data list. Once the data has been received and UI updated, you then call this method to signify that the loading has completed. This method will change the infinite scroll's state from `loading` to `enabled`. |
| `waitFor` | Pass a promise inside `waitFor()` within the `infinite` output event handler in order to change state of infiniteScroll to "complete" |
----------------------------------------------

View File

@ -139,7 +139,7 @@ export class Item {
}
render() {
const { href, detail, mode, win, state, detailIcon, el, routerDirection, type } = this;
const { href, detail, mode, win, state, detailIcon, routerDirection, type } = this;
const clickable = this.isClickable();
const TagType = clickable ? (href ? 'a' : 'button') : 'div';
@ -161,7 +161,7 @@ export class Item {
{ showDetail && <ion-icon icon={detailIcon} lazy={false} class="item-detail-icon"></ion-icon> }
</div>
{ state && <div class="item-state"></div> }
{ clickable && mode === 'md' && <ion-ripple-effect tapClick={true} parent={el} /> }
{ clickable && mode === 'md' && <ion-ripple-effect /> }
</TagType>
);
}

View File

@ -6,14 +6,6 @@ The ripple effect component adds the [Material Design ink ripple interaction eff
<!-- Auto Generated Below -->
## Properties
| Property | Attribute | Description | Type |
| ---------- | ----------- | ---------------------------------------------------------------------- | ----------------------- |
| `parent` | `parent` | | `HTMLElement`, `string` |
| `tapClick` | `tap-click` | If true, the ripple effect will listen to any click events and animate | `boolean` |
## Methods
| Method | Description |

View File

@ -1,6 +1,4 @@
import { Component, Element, EventListenerEnable, Listen, Method, Prop, QueueApi, Watch } from '@stencil/core';
import { now } from '../../utils/helpers';
import { Component, Element, Method, Prop, QueueApi } from '@stencil/core';
@Component({
tag: 'ion-ripple-effect',
@ -9,48 +7,11 @@ import { now } from '../../utils/helpers';
})
export class RippleEffect {
private lastClick = -10000;
@Element() el!: HTMLElement;
@Prop({ context: 'queue' }) queue!: QueueApi;
@Prop({ context: 'enableListener' }) enableListener!: EventListenerEnable;
@Prop({ context: 'window' }) win!: Window;
@Prop() parent?: HTMLElement | string = 'parent';
/** If true, the ripple effect will listen to any click events and animate */
@Prop() tapClick = false;
@Watch('tapClick')
tapClickChanged(tapClick: boolean) {
this.enableListener(this, 'ionActivated', tapClick, this.parent);
this.enableListener(this, 'touchstart', !tapClick);
this.enableListener(this, 'mousedown', !tapClick);
}
@Listen('ionActivated', { enabled: false })
ionActivated(ev: CustomEvent) {
this.addRipple(ev.detail.x, ev.detail.y);
}
@Listen('touchstart', { passive: true, enabled: false })
touchStart(ev: TouchEvent) {
this.lastClick = now(ev);
const touches = ev.touches[0];
this.addRipple(touches.clientX, touches.clientY);
}
@Listen('mousedown', { passive: true, enabled: false })
mouseDown(ev: MouseEvent) {
const timeStamp = now(ev);
if (this.lastClick < (timeStamp - 1000)) {
this.addRipple(ev.pageX, ev.pageY);
}
}
componentDidLoad() {
this.tapClickChanged(this.tapClick);
}
/**
* Adds the ripple effect to the parent element
*/

View File

@ -75,7 +75,7 @@ export class SegmentButton {
disabled={this.disabled}
onClick={() => this.checked = true }>
<slot></slot>
{ this.mode === 'md' && <ion-ripple-effect tapClick={true} parent={this.el}/> }
{ this.mode === 'md' && <ion-ripple-effect /> }
</button>
];
}

View File

@ -500,7 +500,7 @@ export class Select {
onBlur={this.onBlur.bind(this)}
class="select-cover">
<slot></slot>
{ this.mode === 'md' && <ion-ripple-effect tapClick={true}/> }
{ this.mode === 'md' && <ion-ripple-effect /> }
</button>
];
}

View File

@ -130,13 +130,12 @@ export class Tabbar {
if (!tab.disabled) {
this.ionTabbarClick.emit(tab);
}
ev.stopPropagation();
ev.preventDefault();
}}>
{ icon && <ion-icon class="tab-btn-icon" icon={icon} lazy={false}></ion-icon> }
{ label && <span class="tab-btn-text">{label}</span> }
{ badge && <ion-badge class="tab-btn-badge" color={badgeColor}>{badge}</ion-badge> }
{ this.mode === 'md' && <ion-ripple-effect tapClick={true}></ion-ripple-effect> }
{ this.mode === 'md' && <ion-ripple-effect /> }
</a>
);
}

View File

@ -109,11 +109,10 @@ export function startTapClick(doc: Document) {
lastActivated = Date.now();
el.classList.add(ACTIVATED);
const event = new CustomEvent('ionActivated', {
bubbles: false,
detail: { x, y }
});
el.dispatchEvent(event);
const rippleEffect = getRippleEffect(el);
if (rippleEffect && rippleEffect.addRipple) {
rippleEffect.addRipple(x, y);
}
}
function removeActivated(smooth: boolean) {
@ -159,6 +158,16 @@ function getActivatableTarget(ev: any): any {
}
}
function getRippleEffect(el: HTMLElement) {
if (el.shadowRoot) {
const ripple = el.shadowRoot.querySelector('ion-ripple-effect');
if (ripple) {
return ripple;
}
}
return el.querySelector('ion-ripple-effect');
}
const ACTIVATED = 'activated';
const ADD_ACTIVATED_DEFERS = 200;
const CLEAR_STATE_DEFERS = 200;