igniteui-webcomponents
Version:
Ignite UI for Web Components is a complete library of UI components, giving you the ability to build modern web applications using encapsulation and the concept of reusable components in a dependency-free approach.
154 lines • 4.79 kB
JavaScript
const Events = [
'pointerdown',
'pointermove',
'lostpointercapture',
'pointercancel',
];
const defaultState = Object.freeze({ x: 0, y: 0, time: 0 });
export class SwipeEvent extends Event {
constructor(name, data, initOptions) {
super(name, initOptions);
this.name = name;
this.data = data;
}
}
class GesturesController extends EventTarget {
get _element() {
return this._ref ? this._ref.value : this._host;
}
get options() {
return this._options;
}
constructor(host, options) {
super();
this._options = {
thresholdDistance: 100,
thresholdTime: 500,
touchOnly: false,
};
this._pointerState = {
captured: false,
start: defaultState,
current: defaultState,
};
Object.assign(this._options, options);
this._ref = this._options.ref;
this._host = host;
this._host.addController(this);
}
set(type, callback, options) {
const bound = callback.bind(this._host);
this.addEventListener(type, bound, options);
return this;
}
handleEvent(event) {
if (this._options.touchOnly && event.pointerType === 'mouse') {
return;
}
switch (event.type) {
case 'pointerdown':
return this._handlePointerDown(event);
case 'pointermove':
return this._handlePointerMove(event);
case 'lostpointercapture':
case 'pointercancel':
return this._handleLostPointerCapture(event);
}
}
async hostConnected() {
await this._host.updateComplete;
for (const event of Events) {
this._element.addEventListener(event, this, { passive: true });
}
}
hostDisconnected() {
for (const event of Events) {
this._element.removeEventListener(event, this);
}
}
updateOptions(options) {
Object.assign(this._options, options);
}
_getGestureState({ clientX: x, clientY: y, }) {
return { x, y, time: Date.now() };
}
_setTouchActionState(disabled) {
Object.assign(this._element.style, {
touchAction: disabled ? 'none' : undefined,
});
}
_resetState() {
this._pointerState.start = defaultState;
this._pointerState.current = defaultState;
}
_setPointerCaptureState(event, state) {
this._pointerState.captured = state;
state
? this._element.setPointerCapture(event.pointerId)
: this._element.releasePointerCapture(event.pointerId);
}
_handlePointerDown(event) {
this._setTouchActionState(true);
this._pointerState.start = this._getGestureState(event);
this._setPointerCaptureState(event, true);
}
_handlePointerMove(event) {
if (this._pointerState.captured) {
this._pointerState.current = this._getGestureState(event);
}
}
_emit(name, data) {
return this.dispatchEvent(new SwipeEvent(name, data));
}
_createEventArgs() {
const { start, current } = this._pointerState;
return {
xStart: start.x,
xEnd: current.x,
yStart: start.y,
yEnd: current.y,
};
}
_recognize() {
const { start, current } = this._pointerState;
const dt = current.time - start.time;
const dx = current.x - start.x;
const dy = current.y - start.y;
const time = this._options.thresholdTime ?? 500;
const distance = this._options.thresholdDistance ?? 100;
if (dt > time) {
return false;
}
if (dx > distance && Math.abs(dy) < distance) {
return 'right';
}
if (-dx > distance && Math.abs(dy) < distance) {
return 'left';
}
if (dy > distance && Math.abs(dx) < distance) {
return 'down';
}
if (-dy > distance && Math.abs(dx) < distance) {
return 'up';
}
return false;
}
_handleLostPointerCapture(event) {
this._setPointerCaptureState(event, false);
const state = this._recognize();
if (state) {
const args = Object.assign(this._createEventArgs(), {
type: event.pointerType,
direction: state,
});
this._emit('swipe', args);
this._emit(`swipe-${state}`, args);
}
this._resetState();
this._setTouchActionState(false);
}
}
export function addGesturesController(host, options) {
return new GesturesController(host, options);
}
//# sourceMappingURL=gestures.js.map