mirror of
https://github.com/ionic-team/ionic-framework.git
synced 2025-08-22 21:48:42 +08:00
feat(tapclick): adds tap-click
This commit is contained in:
63
packages/core/src/components.d.ts
vendored
63
packages/core/src/components.d.ts
vendored
@ -923,36 +923,6 @@ declare global {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
import {
|
|
||||||
GestureController as IonGestureController
|
|
||||||
} from './components/gesture-controller/gesture-controller';
|
|
||||||
|
|
||||||
declare global {
|
|
||||||
interface HTMLIonGestureControllerElement extends IonGestureController, HTMLElement {
|
|
||||||
}
|
|
||||||
var HTMLIonGestureControllerElement: {
|
|
||||||
prototype: HTMLIonGestureControllerElement;
|
|
||||||
new (): HTMLIonGestureControllerElement;
|
|
||||||
};
|
|
||||||
interface HTMLElementTagNameMap {
|
|
||||||
"ion-gesture-controller": HTMLIonGestureControllerElement;
|
|
||||||
}
|
|
||||||
interface ElementTagNameMap {
|
|
||||||
"ion-gesture-controller": HTMLIonGestureControllerElement;
|
|
||||||
}
|
|
||||||
namespace JSX {
|
|
||||||
interface IntrinsicElements {
|
|
||||||
"ion-gesture-controller": JSXElements.IonGestureControllerAttributes;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
namespace JSXElements {
|
|
||||||
export interface IonGestureControllerAttributes extends HTMLAttributes {
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
import {
|
import {
|
||||||
Gesture as IonGesture
|
Gesture as IonGesture
|
||||||
} from './components/gesture/gesture';
|
} from './components/gesture/gesture';
|
||||||
@ -2295,7 +2265,7 @@ declare global {
|
|||||||
}
|
}
|
||||||
namespace JSXElements {
|
namespace JSXElements {
|
||||||
export interface IonRippleEffectAttributes extends HTMLAttributes {
|
export interface IonRippleEffectAttributes extends HTMLAttributes {
|
||||||
|
useTapClick?: boolean;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2449,7 +2419,6 @@ declare global {
|
|||||||
namespace JSXElements {
|
namespace JSXElements {
|
||||||
export interface IonScrollAttributes extends HTMLAttributes {
|
export interface IonScrollAttributes extends HTMLAttributes {
|
||||||
enabled?: boolean;
|
enabled?: boolean;
|
||||||
jsScroll?: boolean;
|
|
||||||
onionScroll?: ScrollCallback;
|
onionScroll?: ScrollCallback;
|
||||||
onionScrollEnd?: ScrollCallback;
|
onionScrollEnd?: ScrollCallback;
|
||||||
onionScrollStart?: ScrollCallback;
|
onionScrollStart?: ScrollCallback;
|
||||||
@ -2970,6 +2939,36 @@ declare global {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
import {
|
||||||
|
TapClick as IonTapClick
|
||||||
|
} from './components/tap-click/tap-click';
|
||||||
|
|
||||||
|
declare global {
|
||||||
|
interface HTMLIonTapClickElement extends IonTapClick, HTMLElement {
|
||||||
|
}
|
||||||
|
var HTMLIonTapClickElement: {
|
||||||
|
prototype: HTMLIonTapClickElement;
|
||||||
|
new (): HTMLIonTapClickElement;
|
||||||
|
};
|
||||||
|
interface HTMLElementTagNameMap {
|
||||||
|
"ion-tap-click": HTMLIonTapClickElement;
|
||||||
|
}
|
||||||
|
interface ElementTagNameMap {
|
||||||
|
"ion-tap-click": HTMLIonTapClickElement;
|
||||||
|
}
|
||||||
|
namespace JSX {
|
||||||
|
interface IntrinsicElements {
|
||||||
|
"ion-tap-click": JSXElements.IonTapClickAttributes;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
namespace JSXElements {
|
||||||
|
export interface IonTapClickAttributes extends HTMLAttributes {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
import {
|
import {
|
||||||
Text as IonText
|
Text as IonText
|
||||||
} from './components/text/text';
|
} from './components/text/text';
|
||||||
|
@ -3,6 +3,7 @@ import { Config, Nav, NavContainer } from '../../index';
|
|||||||
import { isReady } from '../../utils/helpers';
|
import { isReady } from '../../utils/helpers';
|
||||||
|
|
||||||
const rootNavs = new Map<number, NavContainer>();
|
const rootNavs = new Map<number, NavContainer>();
|
||||||
|
const ACTIVE_SCROLLING_TIME = 100;
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
tag: 'ion-app',
|
tag: 'ion-app',
|
||||||
@ -16,6 +17,9 @@ const rootNavs = new Map<number, NavContainer>();
|
|||||||
})
|
})
|
||||||
export class App {
|
export class App {
|
||||||
|
|
||||||
|
private didScroll = false;
|
||||||
|
private scrollTime = 0;
|
||||||
|
|
||||||
@Element() element: HTMLElement;
|
@Element() element: HTMLElement;
|
||||||
|
|
||||||
@State() modeCode: string;
|
@State() modeCode: string;
|
||||||
@ -27,7 +31,7 @@ export class App {
|
|||||||
componentWillLoad() {
|
componentWillLoad() {
|
||||||
this.modeCode = this.config.get('mode');
|
this.modeCode = this.config.get('mode');
|
||||||
this.useRouter = this.config.getBoolean('useRouter', false);
|
this.useRouter = this.config.getBoolean('useRouter', false);
|
||||||
this.hoverCSS = this.config.getBoolean('hoverCSS', true);
|
this.hoverCSS = this.config.getBoolean('hoverCSS', false);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Listen('body:navInit')
|
@Listen('body:navInit')
|
||||||
@ -35,7 +39,6 @@ export class App {
|
|||||||
rootNavs.set((event.detail as Nav).navId, (event.detail as Nav));
|
rootNavs.set((event.detail as Nav).navId, (event.detail as Nav));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns an array of top level Navs
|
* Returns an array of top level Navs
|
||||||
*/
|
*/
|
||||||
@ -48,16 +51,36 @@ export class App {
|
|||||||
return navs;
|
return navs;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Method()
|
||||||
/**
|
isEnabled(): boolean {
|
||||||
* Check if the app is currently scrolling
|
return true;
|
||||||
*/
|
|
||||||
@Method() isScrolling(): boolean {
|
|
||||||
// TODO - sync with Manu
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Method() getActiveNavs(rootNavId?: number): NavContainer[] {
|
/**
|
||||||
|
* Boolean if the app is actively scrolling or not.
|
||||||
|
* @return {boolean} returns true or false
|
||||||
|
*/
|
||||||
|
@Method()
|
||||||
|
isScrolling(): boolean {
|
||||||
|
const scrollTime = this.scrollTime;
|
||||||
|
if (scrollTime === 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (scrollTime < Date.now()) {
|
||||||
|
this.scrollTime = 0;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Method()
|
||||||
|
setScrolling() {
|
||||||
|
this.scrollTime = Date.now() + ACTIVE_SCROLLING_TIME;
|
||||||
|
this.didScroll = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Method()
|
||||||
|
getActiveNavs(rootNavId?: number): NavContainer[] {
|
||||||
/*const portal = portals.get(PORTAL_MODAL);
|
/*const portal = portals.get(PORTAL_MODAL);
|
||||||
if (portal && portal.views && portal.views.length) {
|
if (portal && portal.views && portal.views.length) {
|
||||||
return findTopNavs(portal);
|
return findTopNavs(portal);
|
||||||
@ -81,7 +104,8 @@ export class App {
|
|||||||
return activeNavs;
|
return activeNavs;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Method() getNavByIdOrName(nameOrId: number | string) {
|
@Method()
|
||||||
|
getNavByIdOrName(nameOrId: number | string) {
|
||||||
const navs = Array.from(rootNavs.values());
|
const navs = Array.from(rootNavs.values());
|
||||||
for (const navContainer of navs) {
|
for (const navContainer of navs) {
|
||||||
const match = getNavByIdOrNameImpl(navContainer, nameOrId);
|
const match = getNavByIdOrNameImpl(navContainer, nameOrId);
|
||||||
@ -102,8 +126,9 @@ export class App {
|
|||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const dom = [<slot></slot>];
|
const dom = [<ion-tap-click />, <slot></slot>];
|
||||||
if (this.useRouter) {
|
if (this.useRouter) {
|
||||||
|
|
||||||
// dom.push(<ion-router-controller></ion-router-controller>);
|
// dom.push(<ion-router-controller></ion-router-controller>);
|
||||||
}
|
}
|
||||||
return dom;
|
return dom;
|
||||||
|
@ -18,9 +18,15 @@
|
|||||||
Returns an array of top level Navs
|
Returns an array of top level Navs
|
||||||
|
|
||||||
|
|
||||||
|
#### isEnabled()
|
||||||
|
|
||||||
|
|
||||||
#### isScrolling()
|
#### isScrolling()
|
||||||
|
|
||||||
Check if the app is currently scrolling
|
Boolean if the app is actively scrolling or not.
|
||||||
|
|
||||||
|
|
||||||
|
#### setScrolling()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -30,7 +30,7 @@
|
|||||||
background-color: $button-ios-background-color-focused;
|
background-color: $button-ios-background-color-focused;
|
||||||
}
|
}
|
||||||
|
|
||||||
.button-ios:hover:not(.disable-hover) {
|
.enable-hover .button-ios:hover {
|
||||||
opacity: $button-ios-opacity-hover;
|
opacity: $button-ios-opacity-hover;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -169,7 +169,7 @@
|
|||||||
background-color: $button-ios-clear-background-color-focused;
|
background-color: $button-ios-clear-background-color-focused;
|
||||||
}
|
}
|
||||||
|
|
||||||
.button-clear-ios:hover:not(.disable-hover) {
|
.enable-hover .button-clear-ios:hover {
|
||||||
color: $button-ios-clear-text-color-hover;
|
color: $button-ios-clear-text-color-hover;
|
||||||
opacity: $button-ios-clear-opacity-hover;
|
opacity: $button-ios-clear-opacity-hover;
|
||||||
}
|
}
|
||||||
@ -196,7 +196,7 @@
|
|||||||
background-color: $bg-color-focused;
|
background-color: $bg-color-focused;
|
||||||
}
|
}
|
||||||
|
|
||||||
.button-clear-ios-#{$color-name}:hover:not(.disable-hover) {
|
.enable-hover .button-clear-ios-#{$color-name}:hover {
|
||||||
color: $fg-color;
|
color: $fg-color;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -29,7 +29,7 @@
|
|||||||
color $button-md-transition-duration $button-md-transition-timing-function;
|
color $button-md-transition-duration $button-md-transition-timing-function;
|
||||||
}
|
}
|
||||||
|
|
||||||
.button-md:hover:not(.disable-hover) {
|
.enable-hover .button-md:hover {
|
||||||
background-color: $button-md-background-color-hover;
|
background-color: $button-md-background-color-hover;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -61,7 +61,7 @@
|
|||||||
background-color: $bg-color;
|
background-color: $bg-color;
|
||||||
}
|
}
|
||||||
|
|
||||||
.button-md-#{$color-name}:hover:not(.disable-hover) {
|
.enable-hover .button-md-#{$color-name}:hover {
|
||||||
background-color: $bg-color;
|
background-color: $bg-color;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -129,7 +129,7 @@
|
|||||||
box-shadow: $button-md-outline-box-shadow;
|
box-shadow: $button-md-outline-box-shadow;
|
||||||
}
|
}
|
||||||
|
|
||||||
.button-outline-md:hover:not(.disable-hover) {
|
.enable-hover .button-outline-md:hover {
|
||||||
background-color: $button-md-outline-background-color-hover;
|
background-color: $button-md-outline-background-color-hover;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -161,7 +161,7 @@
|
|||||||
background-color: $button-md-outline-background-color;
|
background-color: $button-md-outline-background-color;
|
||||||
}
|
}
|
||||||
|
|
||||||
.button-outline-md-#{$color-name}:hover:not(.disable-hover) {
|
.enable-hover .button-outline-md-#{$color-name}:hover {
|
||||||
background-color: $button-md-outline-background-color-hover;
|
background-color: $button-md-outline-background-color-hover;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -199,7 +199,7 @@
|
|||||||
background-color: $button-md-clear-background-color-focused;
|
background-color: $button-md-clear-background-color-focused;
|
||||||
}
|
}
|
||||||
|
|
||||||
.button-clear-md:hover:not(.disable-hover) {
|
.enable-hover .button-clear-md:hover {
|
||||||
background-color: $button-md-clear-background-color-hover;
|
background-color: $button-md-clear-background-color-hover;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -230,7 +230,7 @@
|
|||||||
background-color: $bg-color-focused;
|
background-color: $bg-color-focused;
|
||||||
}
|
}
|
||||||
|
|
||||||
.button-clear-md-#{$color-name}:hover:not(.disable-hover) {
|
.enable-hover .button-clear-md-#{$color-name}:hover {
|
||||||
color: $fg-color;
|
color: $fg-color;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -111,18 +111,16 @@ export class Button {
|
|||||||
strong
|
strong
|
||||||
} = this;
|
} = this;
|
||||||
|
|
||||||
const elementClasses: string[] = []
|
const elementClasses = [
|
||||||
.concat(
|
...getButtonClassList(buttonType, mode),
|
||||||
getButtonClassList(buttonType, mode),
|
...getClassList(buttonType, expand, mode),
|
||||||
getClassList(buttonType, expand, mode),
|
...getClassList(buttonType, size, mode),
|
||||||
getClassList(buttonType, size, mode),
|
...getClassList(buttonType, round ? 'round' : null, mode),
|
||||||
getClassList(buttonType, round ? 'round' : null, mode),
|
...getClassList(buttonType, strong ? 'strong' : null, mode),
|
||||||
getClassList(buttonType, strong ? 'strong' : null, mode),
|
...getColorClassList(buttonType, color, fill, mode),
|
||||||
getColorClassList(buttonType, color, fill, mode),
|
];
|
||||||
);
|
|
||||||
|
|
||||||
const TagType = this.href ? 'a' : 'button';
|
const TagType = this.href ? 'a' : 'button';
|
||||||
|
|
||||||
const buttonClasses = {
|
const buttonClasses = {
|
||||||
...getElementClassObject(this.el.classList),
|
...getElementClassObject(this.el.classList),
|
||||||
...getElementClassObject(elementClasses),
|
...getElementClassObject(elementClasses),
|
||||||
@ -143,7 +141,7 @@ export class Button {
|
|||||||
<slot></slot>
|
<slot></slot>
|
||||||
<slot name='end'></slot>
|
<slot name='end'></slot>
|
||||||
</span>
|
</span>
|
||||||
{ this.mode === 'md' && <ion-ripple-effect /> }
|
{ this.mode === 'md' && <ion-ripple-effect useTapClick={true} /> }
|
||||||
</TagType>
|
</TagType>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -101,7 +101,7 @@ export class ChipButton {
|
|||||||
<span class='button-inner'>
|
<span class='button-inner'>
|
||||||
<slot></slot>
|
<slot></slot>
|
||||||
</span>
|
</span>
|
||||||
{ this.mode === 'md' && <ion-ripple-effect /> }
|
{ this.mode === 'md' && <ion-ripple-effect useTapClick={true} /> }
|
||||||
</TagType>
|
</TagType>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -69,11 +69,6 @@ export class Content {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@Method()
|
|
||||||
enableJsScroll() {
|
|
||||||
this.scrollEl.jsScroll = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Scroll to the top of the content component.
|
* Scroll to the top of the content component.
|
||||||
*
|
*
|
||||||
|
@ -80,9 +80,6 @@ Emitted when the scrolling first starts.
|
|||||||
|
|
||||||
## Methods
|
## Methods
|
||||||
|
|
||||||
#### enableJsScroll()
|
|
||||||
|
|
||||||
|
|
||||||
#### scrollToBottom()
|
#### scrollToBottom()
|
||||||
|
|
||||||
Scroll to the bottom of the content component.
|
Scroll to the bottom of the content component.
|
||||||
|
@ -139,7 +139,7 @@ export class FabButton {
|
|||||||
<span class='button-inner'>
|
<span class='button-inner'>
|
||||||
<slot></slot>
|
<slot></slot>
|
||||||
</span>
|
</span>
|
||||||
{ this.mode === 'md' && <ion-ripple-effect /> }
|
{ this.mode === 'md' && <ion-ripple-effect useTapClick={true} /> }
|
||||||
</TagType>
|
</TagType>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -1,16 +1,11 @@
|
|||||||
import { Component } from '@stencil/core';
|
|
||||||
|
|
||||||
|
|
||||||
@Component({
|
|
||||||
tag: 'ion-gesture-controller'
|
|
||||||
})
|
|
||||||
export class GestureController {
|
export class GestureController {
|
||||||
private gestureId = 0;
|
|
||||||
private requestedStart: { [eventId: number]: number } = {};
|
|
||||||
private disabledGestures: { [eventName: string]: Set<number> } = {};
|
|
||||||
private disabledScroll: Set<number> = new Set<number>();
|
|
||||||
private capturedId: number = null;
|
|
||||||
|
|
||||||
|
private gestureId = 0;
|
||||||
|
private requestedStart = new Map<number, number>();
|
||||||
|
private disabledGestures = new Map<string, Set<number>>();
|
||||||
|
private disabledScroll = new Set<number>();
|
||||||
|
private capturedId: number = null;
|
||||||
|
|
||||||
createGesture(gestureName: string, gesturePriority: number, disableScroll: boolean): GestureDelegate {
|
createGesture(gestureName: string, gesturePriority: number, disableScroll: boolean): GestureDelegate {
|
||||||
return new GestureDelegate(this, this.newID(), gestureName, gesturePriority, disableScroll);
|
return new GestureDelegate(this, this.newID(), gestureName, gesturePriority, disableScroll);
|
||||||
@ -29,11 +24,10 @@ export class GestureController {
|
|||||||
|
|
||||||
start(gestureName: string, id: number, priority: number): boolean {
|
start(gestureName: string, id: number, priority: number): boolean {
|
||||||
if (!this.canStart(gestureName)) {
|
if (!this.canStart(gestureName)) {
|
||||||
delete this.requestedStart[id];
|
this.requestedStart.delete(id);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
this.requestedStart.set(id, priority);
|
||||||
this.requestedStart[id] = priority;
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -43,22 +37,22 @@ export class GestureController {
|
|||||||
}
|
}
|
||||||
const requestedStart = this.requestedStart;
|
const requestedStart = this.requestedStart;
|
||||||
let maxPriority = -10000;
|
let maxPriority = -10000;
|
||||||
for (const gestureID in requestedStart) {
|
for (const value of requestedStart.values()) {
|
||||||
maxPriority = Math.max(maxPriority, requestedStart[gestureID]);
|
maxPriority = Math.max(maxPriority, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (maxPriority === priority) {
|
if (maxPriority === priority) {
|
||||||
this.capturedId = id;
|
this.capturedId = id;
|
||||||
this.requestedStart = {};
|
this.requestedStart.clear();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
delete requestedStart[id];
|
requestedStart.delete(id);
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
release(id: number) {
|
release(id: number) {
|
||||||
delete this.requestedStart[id];
|
this.requestedStart.delete(id);
|
||||||
|
|
||||||
if (this.capturedId && id === this.capturedId) {
|
if (this.capturedId && id === this.capturedId) {
|
||||||
this.capturedId = null;
|
this.capturedId = null;
|
||||||
@ -66,16 +60,16 @@ export class GestureController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
disableGesture(gestureName: string, id: number) {
|
disableGesture(gestureName: string, id: number) {
|
||||||
let set = this.disabledGestures[gestureName];
|
let set = this.disabledGestures.get(gestureName);
|
||||||
if (!set) {
|
if (!set) {
|
||||||
set = new Set<number>();
|
set = new Set<number>();
|
||||||
this.disabledGestures[gestureName] = set;
|
this.disabledGestures.set(gestureName, set);
|
||||||
}
|
}
|
||||||
set.add(id);
|
set.add(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
enableGesture(gestureName: string, id: number) {
|
enableGesture(gestureName: string, id: number) {
|
||||||
const set = this.disabledGestures[gestureName];
|
const set = this.disabledGestures.get(gestureName);
|
||||||
if (set) {
|
if (set) {
|
||||||
set.delete(id);
|
set.delete(id);
|
||||||
}
|
}
|
||||||
@ -121,7 +115,7 @@ export class GestureController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
isDisabled(gestureName: string): boolean {
|
isDisabled(gestureName: string): boolean {
|
||||||
const disabled = this.disabledGestures[gestureName];
|
const disabled = this.disabledGestures.get(gestureName);
|
||||||
if (disabled && disabled.size > 0) {
|
if (disabled && disabled.size > 0) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -99,7 +99,7 @@ export class Item {
|
|||||||
</div>
|
</div>
|
||||||
<slot name='end'></slot>
|
<slot name='end'></slot>
|
||||||
</div>
|
</div>
|
||||||
{ this.href && this.mode === 'md' && <ion-ripple-effect /> }
|
{ this.href && this.mode === 'md' && <ion-ripple-effect useTapClick={true} /> }
|
||||||
</TagType>
|
</TagType>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -5,6 +5,25 @@
|
|||||||
<!-- Auto Generated Below -->
|
<!-- Auto Generated Below -->
|
||||||
|
|
||||||
|
|
||||||
|
## Properties
|
||||||
|
|
||||||
|
#### useTapClick
|
||||||
|
|
||||||
|
boolean
|
||||||
|
|
||||||
|
|
||||||
|
## Attributes
|
||||||
|
|
||||||
|
#### useTapClick
|
||||||
|
|
||||||
|
boolean
|
||||||
|
|
||||||
|
|
||||||
|
## Methods
|
||||||
|
|
||||||
|
#### addRipple()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
----------------------------------------------
|
----------------------------------------------
|
||||||
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { Component, Element, Listen, Prop } from '@stencil/core';
|
import { Component, Element, EventListenerEnable, Listen, Method, Prop } from '@stencil/core';
|
||||||
import { now } from '../../utils/helpers';
|
import { now } from '../../utils/helpers';
|
||||||
import { DomController } from '../../global/dom-controller';
|
import { DomController } from '../../global/dom-controller';
|
||||||
|
|
||||||
@ -12,15 +12,23 @@ export class RippleEffect {
|
|||||||
@Element() el: HTMLElement;
|
@Element() el: HTMLElement;
|
||||||
|
|
||||||
@Prop({context: 'dom'}) dom: DomController;
|
@Prop({context: 'dom'}) dom: DomController;
|
||||||
|
@Prop({context: 'enableListener'}) enableListener: EventListenerEnable;
|
||||||
|
|
||||||
@Listen('touchstart')
|
@Prop() useTapClick = false;
|
||||||
|
|
||||||
|
@Listen('parent:ionActivated', {enabled: false})
|
||||||
|
ionActivated(ev: CustomEvent) {
|
||||||
|
this.addRipple(ev.detail.x, ev.detail.y);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Listen('touchstart', {passive: true, enabled: false})
|
||||||
touchStart(ev: TouchEvent) {
|
touchStart(ev: TouchEvent) {
|
||||||
this.lastClick = now(ev);
|
this.lastClick = now(ev);
|
||||||
const touches = ev.touches[0];
|
const touches = ev.touches[0];
|
||||||
this.addRipple(touches.clientX, touches.clientY);
|
this.addRipple(touches.clientX, touches.clientY);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Listen('mousedown')
|
@Listen('mousedown', {passive: true, enabled: false})
|
||||||
mouseDown(ev: MouseEvent) {
|
mouseDown(ev: MouseEvent) {
|
||||||
const timeStamp = now(ev);
|
const timeStamp = now(ev);
|
||||||
if (this.lastClick < (timeStamp - 1000)) {
|
if (this.lastClick < (timeStamp - 1000)) {
|
||||||
@ -28,7 +36,17 @@ export class RippleEffect {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private addRipple(pageX: number, pageY: number) {
|
componentDidLoad() {
|
||||||
|
if (this.useTapClick) {
|
||||||
|
this.enableListener(this, 'parent:ionActivated', true);
|
||||||
|
} else {
|
||||||
|
this.enableListener(this, 'touchstart', true);
|
||||||
|
this.enableListener(this, 'mousedown', true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Method()
|
||||||
|
addRipple(pageX: number, pageY: number) {
|
||||||
let x: number, y: number, size: number;
|
let x: number, y: number, size: number;
|
||||||
|
|
||||||
this.dom.read(() => {
|
this.dom.read(() => {
|
||||||
|
@ -12,11 +12,6 @@
|
|||||||
boolean
|
boolean
|
||||||
|
|
||||||
|
|
||||||
#### jsScroll
|
|
||||||
|
|
||||||
boolean
|
|
||||||
|
|
||||||
|
|
||||||
#### onionScroll
|
#### onionScroll
|
||||||
|
|
||||||
any
|
any
|
||||||
@ -39,11 +34,6 @@ any
|
|||||||
boolean
|
boolean
|
||||||
|
|
||||||
|
|
||||||
#### jsScroll
|
|
||||||
|
|
||||||
boolean
|
|
||||||
|
|
||||||
|
|
||||||
#### onionScroll
|
#### onionScroll
|
||||||
|
|
||||||
any
|
any
|
||||||
|
@ -12,10 +12,9 @@ export class Scroll {
|
|||||||
|
|
||||||
private gesture: GestureDelegate;
|
private gesture: GestureDelegate;
|
||||||
private positions: number[] = [];
|
private positions: number[] = [];
|
||||||
private _l: number;
|
|
||||||
private _t: number;
|
|
||||||
private tmr: any;
|
private tmr: any;
|
||||||
private queued = false;
|
private queued = false;
|
||||||
|
private app: HTMLIonAppElement;
|
||||||
|
|
||||||
isScrolling = false;
|
isScrolling = false;
|
||||||
detail: ScrollDetail = {};
|
detail: ScrollDetail = {};
|
||||||
@ -27,14 +26,6 @@ export class Scroll {
|
|||||||
@Prop({ context: 'isServer' }) isServer: boolean;
|
@Prop({ context: 'isServer' }) isServer: boolean;
|
||||||
|
|
||||||
@Prop() enabled = true;
|
@Prop() enabled = true;
|
||||||
@Prop() jsScroll = false;
|
|
||||||
|
|
||||||
@Watch('jsScroll')
|
|
||||||
jsScrollChanged(js: boolean) {
|
|
||||||
if (js) {
|
|
||||||
throw new Error('jsScroll: TODO!');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Prop() onionScrollStart: ScrollCallback;
|
@Prop() onionScrollStart: ScrollCallback;
|
||||||
@Prop() onionScroll: ScrollCallback;
|
@Prop() onionScroll: ScrollCallback;
|
||||||
@ -48,7 +39,7 @@ export class Scroll {
|
|||||||
/**
|
/**
|
||||||
* @output {ScrollEvent} Emitted while scrolling.
|
* @output {ScrollEvent} Emitted while scrolling.
|
||||||
*/
|
*/
|
||||||
@Event() ionScroll: EventEmitter;
|
@Event({bubbles: false}) ionScroll: EventEmitter;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @output {ScrollEvent} Emitted when the scroll has ended.
|
* @output {ScrollEvent} Emitted when the scroll has ended.
|
||||||
@ -62,6 +53,7 @@ export class Scroll {
|
|||||||
|
|
||||||
const gestureCtrl = Ionic.gesture = Ionic.gesture || new GestureController();
|
const gestureCtrl = Ionic.gesture = Ionic.gesture || new GestureController();
|
||||||
this.gesture = gestureCtrl.createGesture('scroll', 100, false);
|
this.gesture = gestureCtrl.createGesture('scroll', 100, false);
|
||||||
|
this.app = this.el.closest('ion-app') as HTMLIonAppElement;
|
||||||
}
|
}
|
||||||
|
|
||||||
componentDidUnload() {
|
componentDidUnload() {
|
||||||
@ -69,6 +61,20 @@ export class Scroll {
|
|||||||
this.gesture = this.detail = this.detail.event = null;
|
this.gesture = this.detail = this.detail.event = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Native Scroll *************************
|
||||||
|
|
||||||
|
@Listen('scroll', { passive: true })
|
||||||
|
onNativeScroll() {
|
||||||
|
if (!this.queued) {
|
||||||
|
this.queued = true;
|
||||||
|
|
||||||
|
this.dom.read(timeStamp => {
|
||||||
|
this.queued = false;
|
||||||
|
this.onScroll(timeStamp);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Method()
|
@Method()
|
||||||
scrollToTop(duration: number): Promise<void> {
|
scrollToTop(duration: number): Promise<void> {
|
||||||
return this.scrollToPoint(0, 0, duration);
|
return this.scrollToPoint(0, 0, duration);
|
||||||
@ -106,8 +112,8 @@ export class Scroll {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (duration < 32) {
|
if (duration < 32) {
|
||||||
self.setTop(y);
|
el.scrollTop = y;
|
||||||
self.setLeft(x);
|
el.scrollLeft = x;
|
||||||
done();
|
done();
|
||||||
return promise;
|
return promise;
|
||||||
}
|
}
|
||||||
@ -139,11 +145,11 @@ export class Scroll {
|
|||||||
const easedT = (--time) * time * time + 1;
|
const easedT = (--time) * time * time + 1;
|
||||||
|
|
||||||
if (fromY !== y) {
|
if (fromY !== y) {
|
||||||
self.setTop((easedT * (y - fromY)) + fromY);
|
el.scrollTop = (easedT * (y - fromY)) + fromY;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fromX !== x) {
|
if (fromX !== x) {
|
||||||
self.setLeft(Math.floor((easedT * (x - fromX)) + fromX));
|
el.scrollLeft = Math.floor((easedT * (x - fromX)) + fromX);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (easedT < 1) {
|
if (easedT < 1) {
|
||||||
@ -173,33 +179,23 @@ export class Scroll {
|
|||||||
return promise;
|
return promise;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Native Scroll *************************
|
|
||||||
|
|
||||||
@Listen('scroll', { passive: true })
|
|
||||||
protected onNativeScroll() {
|
|
||||||
if (!this.queued) {
|
|
||||||
this.queued = true;
|
|
||||||
|
|
||||||
this.dom.read(timeStamp => {
|
|
||||||
this.queued = false;
|
|
||||||
this.onScroll(timeStamp);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private onScroll(timeStamp: number) {
|
private onScroll(timeStamp: number) {
|
||||||
const detail = this.detail;
|
const detail = this.detail;
|
||||||
const positions = this.positions;
|
const positions = this.positions;
|
||||||
|
const el = this.el;
|
||||||
|
if (this.app) {
|
||||||
|
this.app.setScrolling();
|
||||||
|
}
|
||||||
|
|
||||||
detail.timeStamp = timeStamp;
|
detail.timeStamp = timeStamp;
|
||||||
|
|
||||||
// get the current scrollTop
|
// get the current scrollTop
|
||||||
// ******** DOM READ ****************
|
// ******** DOM READ ****************
|
||||||
detail.scrollTop = this.getTop();
|
detail.scrollTop = el.scrollTop;
|
||||||
|
|
||||||
// get the current scrollLeft
|
// get the current scrollLeft
|
||||||
// ******** DOM READ ****************
|
// ******** DOM READ ****************
|
||||||
detail.scrollLeft = this.getLeft();
|
detail.scrollLeft = el.scrollLeft;
|
||||||
|
|
||||||
if (!this.isScrolling) {
|
if (!this.isScrolling) {
|
||||||
// currently not scrolling, so this is a scroll start
|
// currently not scrolling, so this is a scroll start
|
||||||
@ -215,9 +211,8 @@ export class Scroll {
|
|||||||
// emit only on the first scroll event
|
// emit only on the first scroll event
|
||||||
if (this.onionScrollStart) {
|
if (this.onionScrollStart) {
|
||||||
this.onionScrollStart(detail);
|
this.onionScrollStart(detail);
|
||||||
} else {
|
|
||||||
this.ionScrollStart.emit(detail);
|
|
||||||
}
|
}
|
||||||
|
this.ionScrollStart.emit(detail);
|
||||||
}
|
}
|
||||||
|
|
||||||
// actively scrolling
|
// actively scrolling
|
||||||
@ -270,7 +265,6 @@ export class Scroll {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private onEnd(timeStamp: number) {
|
private onEnd(timeStamp: number) {
|
||||||
const detail = this.detail;
|
const detail = this.detail;
|
||||||
|
|
||||||
@ -279,50 +273,9 @@ export class Scroll {
|
|||||||
// emit that the scroll has ended
|
// emit that the scroll has ended
|
||||||
if (this.onionScrollEnd) {
|
if (this.onionScrollEnd) {
|
||||||
this.onionScrollEnd(detail);
|
this.onionScrollEnd(detail);
|
||||||
} else {
|
}
|
||||||
this.ionScrollEnd.emit(detail);
|
this.ionScrollEnd.emit(detail);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/** DOM READ */
|
|
||||||
private getTop() {
|
|
||||||
if (this.jsScroll) {
|
|
||||||
return this._t;
|
|
||||||
}
|
|
||||||
return this._t = this.el.scrollTop;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** DOM READ */
|
|
||||||
private getLeft() {
|
|
||||||
if (this.jsScroll) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
return this._l = this.el.scrollLeft;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** DOM WRITE */
|
|
||||||
private setTop(top: number) {
|
|
||||||
this._t = top;
|
|
||||||
|
|
||||||
if (this.jsScroll) {
|
|
||||||
this.el.style.transform = this.el.style.webkitTransform = `translate3d(${this._l * -1}px,${top * -1}px,0px)`;
|
|
||||||
|
|
||||||
} else {
|
|
||||||
this.el.scrollTop = top;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/** DOM WRITE */
|
|
||||||
private setLeft(left: number) {
|
|
||||||
this._l = left;
|
|
||||||
|
|
||||||
if (this.jsScroll) {
|
|
||||||
this.el.style.transform = this.el.style.webkitTransform = `translate3d(${left * -1}px,${this._t * -1}px,0px)`;
|
|
||||||
|
|
||||||
} else {
|
|
||||||
this.el.scrollLeft = left;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
return (
|
return (
|
||||||
|
@ -149,7 +149,7 @@
|
|||||||
color: $color-base;
|
color: $color-base;
|
||||||
}
|
}
|
||||||
|
|
||||||
.searchbar-ios-#{$color-name} .searchbar-ios-cancel:hover:not(.disable-hover) {
|
.enable-hover .searchbar-ios-#{$color-name} .searchbar-ios-cancel:hover {
|
||||||
color: color-shade($color-base);
|
color: color-shade($color-base);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -36,7 +36,7 @@
|
|||||||
fill: $tabs-ios-tab-icon-color;
|
fill: $tabs-ios-tab-icon-color;
|
||||||
}
|
}
|
||||||
|
|
||||||
.tabbar-ios ion-tab-button:hover:not(.disable-hover),
|
.enable-hover .tabbar-ios ion-tab-button:hover,
|
||||||
.tabbar-ios .tab-selected {
|
.tabbar-ios .tab-selected {
|
||||||
color: $tabs-ios-tab-text-color-active;
|
color: $tabs-ios-tab-text-color-active;
|
||||||
|
|
||||||
|
@ -145,7 +145,7 @@
|
|||||||
fill: rgba($color-contrast, $tabs-md-tab-opacity);
|
fill: rgba($color-contrast, $tabs-md-tab-opacity);
|
||||||
}
|
}
|
||||||
|
|
||||||
.tabbar-md-#{$color-name} ion-tab-button:hover:not(.disable-hover),
|
.enable-hover .tabbar-md-#{$color-name} ion-tab-button:hover,
|
||||||
.tabbar-md-#{$color-name} ion-tab-button.tab-selected {
|
.tabbar-md-#{$color-name} ion-tab-button.tab-selected {
|
||||||
color: $color-contrast;
|
color: $color-contrast;
|
||||||
|
|
||||||
|
11
packages/core/src/components/tap-click/readme.md
Normal file
11
packages/core/src/components/tap-click/readme.md
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
# ion-tap-click
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<!-- Auto Generated Below -->
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
----------------------------------------------
|
||||||
|
|
||||||
|
*Built by [StencilJS](https://stenciljs.com/)*
|
1
packages/core/src/components/tap-click/tap-click.scss
Normal file
1
packages/core/src/components/tap-click/tap-click.scss
Normal file
@ -0,0 +1 @@
|
|||||||
|
@import "../../themes/ionic.globals";
|
190
packages/core/src/components/tap-click/tap-click.tsx
Normal file
190
packages/core/src/components/tap-click/tap-click.tsx
Normal file
@ -0,0 +1,190 @@
|
|||||||
|
import { Component, Element, EventListenerEnable, Listen, Prop } from '@stencil/core';
|
||||||
|
import { now, pointerCoordX, pointerCoordY } from '../../utils/helpers';
|
||||||
|
import { GestureController } from '../gesture-controller/gesture-controller';
|
||||||
|
|
||||||
|
declare const Ionic: { gesture: GestureController };
|
||||||
|
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
tag: 'ion-tap-click',
|
||||||
|
styleUrl: 'tap-click.scss'
|
||||||
|
})
|
||||||
|
export class TapClick {
|
||||||
|
|
||||||
|
private app: HTMLIonAppElement;
|
||||||
|
private lastTouch = 0;
|
||||||
|
private lastActivated = 0;
|
||||||
|
|
||||||
|
private gestureCtrl: GestureController;
|
||||||
|
|
||||||
|
private activatableEle: HTMLElement;
|
||||||
|
private activeDefer: any;
|
||||||
|
|
||||||
|
private clearDefers = new WeakMap<HTMLElement, any>();
|
||||||
|
|
||||||
|
passive = true;
|
||||||
|
attachTo = 'document';
|
||||||
|
|
||||||
|
@Prop({context: 'enableListener'}) enableListener: EventListenerEnable;
|
||||||
|
|
||||||
|
@Element() el: HTMLElement;
|
||||||
|
|
||||||
|
componentDidLoad() {
|
||||||
|
this.gestureCtrl = Ionic.gesture = Ionic.gesture || new GestureController();
|
||||||
|
|
||||||
|
this.app = this.el.closest('ion-app') as HTMLIonAppElement;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Listen('document:click', {passive: false, capture: true})
|
||||||
|
onBodyClick(ev: any) {
|
||||||
|
if (this.shouldCancel()) {
|
||||||
|
ev.preventDefault();
|
||||||
|
ev.stopPropagation();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Touch Events
|
||||||
|
@Listen('document:touchstart', { passive: true })
|
||||||
|
onTouchStart(ev: TouchEvent) {
|
||||||
|
this.lastTouch = now(ev);
|
||||||
|
this.pointerDown(ev);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Listen('document:touchcancel', { passive: true })
|
||||||
|
onTouchCancel(ev: TouchEvent) {
|
||||||
|
this.lastTouch = now(ev);
|
||||||
|
this.pointerUp(ev);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Listen('document:touchend', { passive: true })
|
||||||
|
onTouchEnd(ev: TouchEvent) {
|
||||||
|
this.lastTouch = now(ev);
|
||||||
|
this.pointerUp(ev);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Listen('document:mousedown', { passive: true })
|
||||||
|
onMouseDown(ev: MouseEvent) {
|
||||||
|
const t = now(ev);
|
||||||
|
if (this.lastTouch < t - MOUSE_WAIT) {
|
||||||
|
this.pointerDown(ev);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Listen('document:mouseup', { passive: true })
|
||||||
|
onMouseUp(ev: TouchEvent) {
|
||||||
|
const t = now(ev);
|
||||||
|
if (this.lastTouch < t - MOUSE_WAIT) {
|
||||||
|
this.pointerUp(ev);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Listen('body:ionScrollStart')
|
||||||
|
scrollStarted() {
|
||||||
|
clearTimeout(this.activeDefer);
|
||||||
|
if (this.activatableEle) {
|
||||||
|
this.removeActivated(false);
|
||||||
|
this.activatableEle = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private pointerDown(ev: any) {
|
||||||
|
if (this.activatableEle) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!this.shouldCancel()) {
|
||||||
|
this.setActivatedElement(getActivatableTarget(ev.target), ev);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private pointerUp(ev: UIEvent) {
|
||||||
|
this.setActivatedElement(null, ev);
|
||||||
|
}
|
||||||
|
|
||||||
|
private setActivatedElement(el: HTMLElement, ev: UIEvent) {
|
||||||
|
// do nothing
|
||||||
|
const activatableEle = this.activatableEle;
|
||||||
|
if (el && el === activatableEle) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
clearTimeout(this.activeDefer);
|
||||||
|
this.activeDefer = null;
|
||||||
|
|
||||||
|
const eventX = pointerCoordX(ev);
|
||||||
|
const eventY = pointerCoordY(ev);
|
||||||
|
|
||||||
|
// unactivate selected
|
||||||
|
if (activatableEle) {
|
||||||
|
if (this.clearDefers.has(activatableEle)) {
|
||||||
|
throw new Error('internal error');
|
||||||
|
}
|
||||||
|
if (!activatableEle.classList.contains(ACTIVATED)) {
|
||||||
|
this.addActivated(activatableEle, eventX, eventY);
|
||||||
|
}
|
||||||
|
this.removeActivated(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
// activate
|
||||||
|
if (el) {
|
||||||
|
const deferId = this.clearDefers.get(el);
|
||||||
|
if (deferId) {
|
||||||
|
clearTimeout(deferId);
|
||||||
|
this.clearDefers.delete(el);
|
||||||
|
}
|
||||||
|
|
||||||
|
el.classList.remove(ACTIVATED);
|
||||||
|
this.activeDefer = setTimeout(() => {
|
||||||
|
this.addActivated(el, eventX, eventY);
|
||||||
|
this.activeDefer = null;
|
||||||
|
}, ADD_ACTIVATED_DEFERS);
|
||||||
|
}
|
||||||
|
this.activatableEle = el;
|
||||||
|
}
|
||||||
|
|
||||||
|
private addActivated(el: HTMLElement, x: number, y: number) {
|
||||||
|
this.lastActivated = Date.now();
|
||||||
|
el.classList.add(ACTIVATED);
|
||||||
|
|
||||||
|
const event = new CustomEvent('ionActivated', {
|
||||||
|
bubbles: false,
|
||||||
|
detail: {x, y}
|
||||||
|
});
|
||||||
|
el.dispatchEvent(event);
|
||||||
|
}
|
||||||
|
|
||||||
|
private removeActivated(smooth: boolean) {
|
||||||
|
const activatableEle = this.activatableEle;
|
||||||
|
|
||||||
|
const time = CLEAR_STATE_DEFERS - Date.now() + this.lastActivated;
|
||||||
|
if (smooth && time > 0) {
|
||||||
|
const deferId = setTimeout(() => {
|
||||||
|
activatableEle.classList.remove(ACTIVATED);
|
||||||
|
this.clearDefers.delete(activatableEle);
|
||||||
|
}, CLEAR_STATE_DEFERS);
|
||||||
|
this.clearDefers.set(activatableEle, deferId);
|
||||||
|
} else {
|
||||||
|
activatableEle.classList.remove(ACTIVATED);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private shouldCancel(): boolean {
|
||||||
|
if (!this.app.isEnabled()) {
|
||||||
|
console.debug('click prevent: appDisabled');
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (this.gestureCtrl.isCaptured()) {
|
||||||
|
console.debug('click prevent: tap-click (gesture is captured)');
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function getActivatableTarget(el: HTMLElement): any {
|
||||||
|
return el.closest('a,button,[tappable]');
|
||||||
|
}
|
||||||
|
|
||||||
|
const ACTIVATED = 'activated';
|
||||||
|
const ADD_ACTIVATED_DEFERS = 200;
|
||||||
|
const CLEAR_STATE_DEFERS = 200;
|
||||||
|
const MOUSE_WAIT = 2500;
|
70
packages/core/src/components/tap-click/test/basic/index.html
Normal file
70
packages/core/src/components/tap-click/test/basic/index.html
Normal file
@ -0,0 +1,70 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html dir="ltr">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<title>Button Effect - Basic</title>
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no">
|
||||||
|
<script src="/dist/ionic.js"></script>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.my-block {
|
||||||
|
position: relative;
|
||||||
|
background: blue;
|
||||||
|
color: white;
|
||||||
|
width: 300px;
|
||||||
|
height: 100px;
|
||||||
|
margin: 1rem;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<ion-app>
|
||||||
|
<ion-page>
|
||||||
|
<ion-header>
|
||||||
|
<ion-toolbar>
|
||||||
|
<ion-title>Button Effect - Basic</ion-title>
|
||||||
|
</ion-toolbar>
|
||||||
|
</ion-header>
|
||||||
|
|
||||||
|
<ion-content padding no-bounce>
|
||||||
|
<p>
|
||||||
|
<ion-button size="small">Small</ion-button>
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
<ion-button size="large">Large</ion-button>
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
<ion-button size="large" fill="outline">Large</ion-button>
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
<ion-button size="large" fill="clear">Large</ion-button>
|
||||||
|
</p>
|
||||||
|
<div class="my-block">
|
||||||
|
<ion-ripple-effect></ion-ripple-effect>
|
||||||
|
This is just a div + effect behind
|
||||||
|
<ion-button onclick="buttonClicked()">Nested button</ion-button>
|
||||||
|
</div>
|
||||||
|
<div class="my-block">
|
||||||
|
This is just a div + effect on top
|
||||||
|
<ion-button onclick="buttonClicked()">Nested button</ion-button>
|
||||||
|
<ion-ripple-effect></ion-ripple-effect>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="my-block">
|
||||||
|
This is just a div + effect
|
||||||
|
<ion-ripple-effect></ion-ripple-effect>
|
||||||
|
</div>
|
||||||
|
</ion-content>
|
||||||
|
</ion-page>
|
||||||
|
</ion-app>
|
||||||
|
<script>
|
||||||
|
function blockClicked() {
|
||||||
|
console.log('block clicked');
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
function buttonClicked() {
|
||||||
|
console.log('button clicked');
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
@ -159,15 +159,17 @@
|
|||||||
color: $color-base;
|
color: $color-base;
|
||||||
background-color: transparent;
|
background-color: transparent;
|
||||||
|
|
||||||
&:hover:not(.disable-hover) {
|
|
||||||
color: $color-base;
|
|
||||||
}
|
|
||||||
|
|
||||||
&.activated {
|
&.activated {
|
||||||
opacity: .4;
|
opacity: .4;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.enable-hover .bar-button-#{$color-name}-ios:hover,
|
||||||
|
.enable-hover .bar-button-clear-ios-#{$color-name}:hover,
|
||||||
|
.enable-hover .bar-button-ios-#{$color-name}:hover {
|
||||||
|
color: $color-base;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// iOS Toolbar Button Icon
|
// iOS Toolbar Button Icon
|
||||||
@ -188,16 +190,16 @@
|
|||||||
color: $toolbar-ios-button-color;
|
color: $toolbar-ios-button-color;
|
||||||
background-color: transparent;
|
background-color: transparent;
|
||||||
|
|
||||||
&:hover:not(.disable-hover) {
|
|
||||||
opacity: .4;
|
|
||||||
}
|
|
||||||
|
|
||||||
&.activated {
|
&.activated {
|
||||||
color: color-contrast($colors-ios, $toolbar-ios-button-color);
|
color: color-contrast($colors-ios, $toolbar-ios-button-color);
|
||||||
background-color: $toolbar-ios-button-color;
|
background-color: $toolbar-ios-button-color;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.enable-hover .bar-button-outline-ios:hover {
|
||||||
|
opacity: .4;
|
||||||
|
}
|
||||||
|
|
||||||
@mixin ios-bar-button-outline($color-name, $color-base, $color-contrast) {
|
@mixin ios-bar-button-outline($color-name, $color-base, $color-contrast) {
|
||||||
|
|
||||||
.bar-button-outline-ios-#{$color-name} {
|
.bar-button-outline-ios-#{$color-name} {
|
||||||
@ -222,11 +224,6 @@
|
|||||||
color: color-contrast($colors-ios, $toolbar-ios-button-color);
|
color: color-contrast($colors-ios, $toolbar-ios-button-color);
|
||||||
background-color: $toolbar-ios-button-color;
|
background-color: $toolbar-ios-button-color;
|
||||||
|
|
||||||
&:hover:not(.disable-hover) {
|
|
||||||
color: color-contrast($colors-ios, $toolbar-ios-button-color);
|
|
||||||
opacity: .4;
|
|
||||||
}
|
|
||||||
|
|
||||||
&.activated {
|
&.activated {
|
||||||
color: color-contrast($colors-ios, $toolbar-ios-button-color);
|
color: color-contrast($colors-ios, $toolbar-ios-button-color);
|
||||||
background-color: color-shade($toolbar-ios-button-color);
|
background-color: color-shade($toolbar-ios-button-color);
|
||||||
@ -234,6 +231,11 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.enable-hover .bar-button-solid-ios:hover {
|
||||||
|
color: color-contrast($colors-ios, $toolbar-ios-button-color);
|
||||||
|
opacity: .4;
|
||||||
|
}
|
||||||
|
|
||||||
@mixin ios-bar-button-solid($color-name, $color-base, $color-contrast) {
|
@mixin ios-bar-button-solid($color-name, $color-base, $color-contrast) {
|
||||||
|
|
||||||
.bar-button-solid-ios-#{$color-name} {
|
.bar-button-solid-ios-#{$color-name} {
|
||||||
|
@ -167,10 +167,12 @@
|
|||||||
.bar-button-md-#{$color-name} {
|
.bar-button-md-#{$color-name} {
|
||||||
color: $color-base;
|
color: $color-base;
|
||||||
background-color: transparent;
|
background-color: transparent;
|
||||||
|
|
||||||
&:hover:not(.disable-hover) {
|
|
||||||
color: $color-base;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.enable-hover .bar-button-#{$color-name}-md:hover,
|
||||||
|
.enable-hover .bar-button-clear-md-#{$color-name}:hover,
|
||||||
|
.enable-hover .bar-button-md-#{$color-name}:hover {
|
||||||
|
color: $color-base;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -194,10 +196,6 @@
|
|||||||
color: $toolbar-md-button-color;
|
color: $toolbar-md-button-color;
|
||||||
background-color: transparent;
|
background-color: transparent;
|
||||||
|
|
||||||
&:hover:not(.disable-hover) {
|
|
||||||
opacity: .4;
|
|
||||||
}
|
|
||||||
|
|
||||||
&.activated {
|
&.activated {
|
||||||
background-color: transparent;
|
background-color: transparent;
|
||||||
}
|
}
|
||||||
@ -207,6 +205,10 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.enable-hover .bar-button-outline-md:hover {
|
||||||
|
opacity: .4;
|
||||||
|
}
|
||||||
|
|
||||||
@mixin md-bar-button-outline($color-name, $color-base, $color-contrast) {
|
@mixin md-bar-button-outline($color-name, $color-base, $color-contrast) {
|
||||||
|
|
||||||
.bar-button-outline-md-#{$color-name} {
|
.bar-button-outline-md-#{$color-name} {
|
||||||
@ -234,16 +236,18 @@
|
|||||||
color: color-contrast($colors-md, $toolbar-md-button-color, md);
|
color: color-contrast($colors-md, $toolbar-md-button-color, md);
|
||||||
background-color: $toolbar-md-button-color;
|
background-color: $toolbar-md-button-color;
|
||||||
|
|
||||||
&:hover:not(.disable-hover) {
|
|
||||||
color: color-contrast($colors-md, $toolbar-md-button-color, md);
|
|
||||||
}
|
|
||||||
|
|
||||||
&.activated {
|
&.activated {
|
||||||
color: color-contrast($colors-md, $toolbar-md-button-color, md);
|
color: color-contrast($colors-md, $toolbar-md-button-color, md);
|
||||||
background-color: color-shade($toolbar-md-button-color);
|
background-color: color-shade($toolbar-md-button-color);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.enable-hover .bar-button-solid-md:hover {
|
||||||
|
color: color-contrast($colors-md, $toolbar-md-button-color, md);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@mixin md-bar-button-solid($color-name, $color-base, $color-contrast) {
|
@mixin md-bar-button-solid($color-name, $color-base, $color-contrast) {
|
||||||
|
|
||||||
.bar-button-solid-md-#{$color-name} {
|
.bar-button-solid-md-#{$color-name} {
|
||||||
|
Reference in New Issue
Block a user