feat(haptic): adds haptic utils

This commit is contained in:
Manu Mtz.-Almeida
2017-11-02 12:18:19 +01:00
parent 4e9b4727be
commit ad81cca77a
3 changed files with 86 additions and 31 deletions

View File

@ -1,6 +1,7 @@
import { Component, Element, Prop, PropDidChange, State } from '@stencil/core'; import { Component, Element, Prop, PropDidChange, State } from '@stencil/core';
import { GestureDetail } from '../../index'; import { GestureDetail } from '../../index';
import { clamp, reorderArray } from '../../utils/helpers'; import { clamp, reorderArray } from '../../utils/helpers';
import { hapticSelectionChanged, hapticSelectionEnd, hapticSelectionStart} from '../../utils/haptic';
import { CSS_PROP } from '../animation-controller/constants'; import { CSS_PROP } from '../animation-controller/constants';
const AUTO_SCROLL_MARGIN = 60; const AUTO_SCROLL_MARGIN = 60;
@ -252,9 +253,7 @@ export class ReorderGroup {
item.classList.add(ITEM_REORDER_SELECTED); item.classList.add(ITEM_REORDER_SELECTED);
if ((window as any).TapticEngine) { hapticSelectionStart();
(window as any).TapticEngine.gestureSelectionStart();
}
} }
private onDragMove(ev: GestureDetail) { private onDragMove(ev: GestureDetail) {
@ -276,9 +275,7 @@ export class ReorderGroup {
let fromIndex = indexForItem(selectedItem); let fromIndex = indexForItem(selectedItem);
this.lastToIndex = toIndex; this.lastToIndex = toIndex;
if ((window as any).TapticEngine) { hapticSelectionChanged();
(window as any).TapticEngine.gestureSelectionChanged();
}
this._reorderMove(fromIndex, toIndex); this._reorderMove(fromIndex, toIndex);
} }
@ -321,9 +318,7 @@ export class ReorderGroup {
reorderInactive(); reorderInactive();
} }
if ((window as any).TapticEngine) { hapticSelectionEnd();
(window as any).TapticEngine.gestureSelectionEnd();
}
} }
private itemIndexForTop(deltaY: number): number { private itemIndexForTop(deltaY: number): number {

View File

@ -1,5 +1,6 @@
import { Component, Event, EventEmitter, Listen, Method, Prop, PropDidChange, State } from '@stencil/core'; import { Component, Event, EventEmitter, Listen, Method, Prop, PropDidChange, State } from '@stencil/core';
import { BooleanInputComponent, GestureDetail } from '../../index'; import { BooleanInputComponent, GestureDetail } from '../../index';
import { hapticSelection } from '../../utils/haptic';
@Component({ @Component({
@ -19,7 +20,7 @@ export class Toggle implements BooleanInputComponent {
private labelId: string; private labelId: string;
private styleTmr: any; private styleTmr: any;
private gestureConfig: any; private gestureConfig: any;
private startX: number; private pivotX: number;
hasFocus: boolean = false; hasFocus: boolean = false;
@ -85,39 +86,30 @@ export class Toggle implements BooleanInputComponent {
} }
private onDragStart(detail: GestureDetail) { private onDragStart(detail: GestureDetail) {
this.startX = detail.startX; this.pivotX = detail.currentX;
this.activated = true;
this.fireFocus(); this.fireFocus();
} }
private onDragMove(detail: GestureDetail) { private onDragMove(detail: GestureDetail) {
const currentX = detail.currentX; const currentX = detail.currentX;
if (this.checked) { const checked = this.checked;
if (currentX + 15 < this.startX) { if (shouldToggle(checked, currentX - this.pivotX, -15)) {
this.checked = false; this.checked = !checked;
this.activated = true; this.pivotX = currentX;
this.startX = currentX; hapticSelection();
}
} else if (currentX - 15 > this.startX) {
this.checked = true;
this.activated = (currentX < this.startX + 5);
this.startX = currentX;
} }
} }
private onDragEnd(detail: GestureDetail) { private onDragEnd(detail: GestureDetail) {
const delta = detail.deltaX; const delta = detail.currentX - this.pivotX;
if (this.checked) { const checked = this.checked;
if (delta < -4) { if (shouldToggle(checked, delta, 4)) {
this.checked = false; this.checked = !checked;
} hapticSelection();
} else if (delta > 4) {
this.checked = true;
} }
this.activated = false; this.activated = false;
this.startX = null;
this.fireBlur(); this.fireBlur();
} }
@ -182,3 +174,15 @@ export class Toggle implements BooleanInputComponent {
); );
} }
} }
function shouldToggle(checked: boolean, deltaX: number, margin: number): boolean {
const isRTL = document.dir === 'rtl';
if (checked) {
return (!isRTL && (margin > deltaX)) ||
(isRTL && (- margin < deltaX));
} else {
return (!isRTL && (- margin < deltaX)) ||
(isRTL && (margin > deltaX));
}
}

View File

@ -0,0 +1,56 @@
const _engine = (window as any).TapticEngine;
/**
* Check to see if the Haptic Plugin is available
* @return {boolean} Returns true or false if the plugin is available
*
*/
export function hapticAvailable() {
return !!_engine;
}
/**
* Trigger a selection changed haptic event. Good for one-time events
* (not for gestures)
*/
export function hapticSelection() {
_engine && _engine.selection();
}
/**
* Tell the haptic engine that a gesture for a selection change is starting.
*/
export function hapticSelectionStart() {
_engine && _engine.gestureSelectionStart();
}
/**
* Tell the haptic engine that a selection changed during a gesture.
*/
export function hapticSelectionChanged() {
_engine && _engine.gestureSelectionChanged();
}
/**
* Tell the haptic engine we are done with a gesture. This needs to be
* called lest resources are not properly recycled.
*/
export function hapticSelectionEnd() {
_engine && _engine.gestureSelectionEnd();
}
/**
* Use this to indicate success/failure/warning to the user.
* options should be of the type `{ type: 'success' }` (or `warning`/`error`)
*/
export function hapticNotification(options: { type: string }) {
_engine && _engine.notification(options);
}
/**
* Use this to indicate success/failure/warning to the user.
* options should be of the type `{ style: 'light' }` (or `medium`/`heavy`)
*/
export function hapticImpact(options: { style: string }) {
_engine && _engine.impact(options);
}