Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

wheel-gestures

Package Overview
Dependencies
Maintainers
1
Versions
65
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

wheel-gestures - npm Package Compare versions

Comparing version 1.0.1 to 1.0.2-beta.3

dist/index.d.ts

16

dist/events/EventBus.d.ts

@@ -1,10 +0,10 @@

interface Props<T> {
events: T[];
export interface Props {
}
declare type EventListener = () => void;
export default function EventBus<T extends string>({ events }: Props<T>): Readonly<{
on: (type: T, listener: EventListener) => () => void;
off: (type: T, listener: EventListener) => void;
dispatch: (type: T) => void;
export declare type EventMapEmpty = Record<string, unknown>;
export declare type EventListener<D = unknown> = (data: D) => void;
export declare type Off = () => void;
export default function EventBus<EventMap = EventMapEmpty>({}?: Props): Readonly<{
on: <EK extends keyof EventMap>(type: EK, listener: EventListener<EventMap[EK]>) => Off;
off: <EK_1 extends keyof EventMap>(type: EK_1, listener: EventListener<EventMap[EK_1]>) => void;
dispatch: <EK_2 extends keyof EventMap>(type: EK_2, data: EventMap[EK_2]) => void;
}>;
export {};

@@ -1,21 +0,2 @@

declare type WheelEventDataRequiredFields = 'deltaMode' | 'deltaX' | 'deltaY';
export interface WheelEventData extends Pick<WheelEvent, WheelEventDataRequiredFields>, Partial<Omit<WheelEvent, WheelEventDataRequiredFields>> {
}
export declare type WheelTypes = 'WHEEL' | 'ANY_WHEEL' | 'MOMENTUM_WHEEL';
export declare enum WheelPhase {
'ANY_WHEEL_START' = "ANY_WHEEL_START",
'ANY_WHEEL' = "ANY_WHEEL",
'ANY_WHEEL_END' = "ANY_WHEEL_END",
'WHEEL_START' = "WHEEL_START",
'WHEEL' = "WHEEL",
'WHEEL_END' = "WHEEL_END",
'MOMENTUM_WHEEL_START' = "MOMENTUM_WHEEL_START",
'MOMENTUM_WHEEL' = "MOMENTUM_WHEEL",
'MOMENTUM_WHEEL_CANCEL' = "MOMENTUM_WHEEL_CANCEL",
'MOMENTUM_WHEEL_END' = "MOMENTUM_WHEEL_END"
}
export declare type PhaseData = ReturnType<typeof WheelAnalyzer.prototype.getCurrentState>;
export declare type SubscribeFn = (type: WheelPhase, data: PhaseData) => void;
export declare type Unsubscribe = () => void;
declare type PreventWheelActionType = 'all' | 'x' | 'y';
import { PreventWheelActionType, SubscribeFn, Unobserve, Unsubscribe, WheelEventData, WheelPhase } from './wheel-analyzer.types';
export interface Options {

@@ -27,2 +8,3 @@ preventWheelAction: PreventWheelActionType;

private isStarted;
private isStartPublished;
private isMomentum;

@@ -33,7 +15,2 @@ private lastAbsDelta;

private accelerationFactors;
private deltaVelocity;
private deltaTotal;
/**
* @description merged scrollPoints
*/
private scrollPoints;

@@ -44,5 +21,6 @@ private scrollPointsToMerge;

private options;
private readonly willEnd;
private willEndTimeout;
private willEnd;
constructor(options?: Partial<Options>);
observe: (target: EventTarget) => () => void;
observe: (target: EventTarget) => Unobserve;
unobserve: (target: EventTarget) => void;

@@ -55,5 +33,8 @@ disconnect: () => void;

private shouldPreventDefault;
private clampDelta;
private processWheelEventData;
private debugMessage;
private updateVelocityNew;
private updateStartVelocity;
private updateVelocity;
private updateWillEndTimeout;
private static accelerationFactorInMomentumRange;

@@ -67,4 +48,2 @@ private detectMomentum;

isMomentum: boolean;
deltaVelocity: number;
deltaTotal: number;
axisDeltas: number[];

@@ -75,4 +54,3 @@ axisVelocity: number[];

private end;
private readonly willEndSoon;
private get willEndSoon();
}
export {};

@@ -1,10 +0,12 @@

export * from './wheel-analyzer';
interface Props {
axis: 'x' | 'y' | 'all';
import { WheelGesturesEventMap, WheelReason } from './wheel-gestures.types';
export interface Props {
axis?: 'x' | 'y' | 'all';
wheelReason?: WheelReason;
}
export declare function WheelGestures({ axis }?: Props): Readonly<{
observe: (target: EventTarget) => () => void;
export declare function WheelGestures({ axis, wheelReason }?: Props): Readonly<{
observe: (target: EventTarget) => import("./wheel-analyzer.types").Unobserve;
unobserve: (target: EventTarget) => void;
disconnect: () => void;
on: (type: "wheelpan", listener: () => void) => () => void;
on: <EK extends "wheelstart" | "wheelmove" | "wheelend">(type: EK, listener: import("./events/EventBus").EventListener<WheelGesturesEventMap[EK]>) => import("./events/EventBus").Off;
off: <EK_1 extends "wheelstart" | "wheelmove" | "wheelend">(type: EK_1, listener: import("./events/EventBus").EventListener<WheelGesturesEventMap[EK_1]>) => void;
}>;

@@ -1,41 +0,70 @@

import { debounce } from 'throttle-debounce';
function _defineProperties(target, props) {
for (var i = 0; i < props.length; i++) {
var descriptor = props[i];
descriptor.enumerable = descriptor.enumerable || false;
descriptor.configurable = true;
if ("value" in descriptor) descriptor.writable = true;
Object.defineProperty(target, descriptor.key, descriptor);
}
}
/*! *****************************************************************************
Copyright (c) Microsoft Corporation. All rights reserved.
Licensed under the Apache License, Version 2.0 (the "License"); you may not use
this file except in compliance with the License. You may obtain a copy of the
License at http://www.apache.org/licenses/LICENSE-2.0
function _createClass(Constructor, protoProps, staticProps) {
if (protoProps) _defineProperties(Constructor.prototype, protoProps);
if (staticProps) _defineProperties(Constructor, staticProps);
return Constructor;
}
THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED
WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,
MERCHANTABLITY OR NON-INFRINGEMENT.
function _extends() {
_extends = Object.assign || function (target) {
for (var i = 1; i < arguments.length; i++) {
var source = arguments[i];
See the Apache Version 2.0 License for specific language governing permissions
and limitations under the License.
***************************************************************************** */
var __assign = function() {
__assign = Object.assign || function __assign(t) {
for (var s, i = 1, n = arguments.length; i < n; i++) {
s = arguments[i];
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p];
for (var key in source) {
if (Object.prototype.hasOwnProperty.call(source, key)) {
target[key] = source[key];
}
return t;
};
return __assign.apply(this, arguments);
};
}
}
function __rest(s, e) {
var t = {};
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
t[p] = s[p];
if (s != null && typeof Object.getOwnPropertySymbols === "function")
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
t[p[i]] = s[p[i]];
}
return t;
return target;
};
return _extends.apply(this, arguments);
}
function _objectDestructuringEmpty(obj) {
if (obj == null) throw new TypeError("Cannot destructure undefined");
}
var WheelPhase;
(function (WheelPhase) {
WheelPhase["ANY_WHEEL_START"] = "ANY_WHEEL_START";
WheelPhase["ANY_WHEEL"] = "ANY_WHEEL";
WheelPhase["ANY_WHEEL_END"] = "ANY_WHEEL_END";
WheelPhase["WHEEL_START"] = "WHEEL_START";
WheelPhase["WHEEL"] = "WHEEL";
WheelPhase["WHEEL_END"] = "WHEEL_END";
WheelPhase["MOMENTUM_WHEEL_START"] = "MOMENTUM_WHEEL_START";
WheelPhase["MOMENTUM_WHEEL"] = "MOMENTUM_WHEEL";
WheelPhase["MOMENTUM_WHEEL_CANCEL"] = "MOMENTUM_WHEEL_CANCEL";
WheelPhase["MOMENTUM_WHEEL_END"] = "MOMENTUM_WHEEL_END";
})(WheelPhase || (WheelPhase = {}));
var LINE_HEIGHT = 16 * 1.125;
var PAGE_HEIGHT = typeof window !== 'undefined' && window.innerHeight || 800;
var DELTA_MODE_UNIT = [1, LINE_HEIGHT, PAGE_HEIGHT];
function normalizeWheel(e) {
var deltaX = e.deltaX * DELTA_MODE_UNIT[e.deltaMode];
var deltaY = e.deltaY * DELTA_MODE_UNIT[e.deltaMode];
var deltaZ = (e.deltaZ || 0) * DELTA_MODE_UNIT[e.deltaMode];
return {
deltaX: deltaX,
deltaY: deltaY,
deltaZ: deltaZ,
deltaMode: 0,
timestamp: e.timeStamp
};
}
var WHEELEVENTS_TO_MERGE = 2;

@@ -47,327 +76,510 @@ var WHEELEVENTS_TO_ANALAZE = 5;

var ACC_FACTOR_MAX = 0.96;
var WheelPhase;
(function (WheelPhase) {
WheelPhase["ANY_WHEEL_START"] = "ANY_WHEEL_START";
WheelPhase["ANY_WHEEL"] = "ANY_WHEEL";
WheelPhase["ANY_WHEEL_END"] = "ANY_WHEEL_END";
WheelPhase["WHEEL_START"] = "WHEEL_START";
WheelPhase["WHEEL"] = "WHEEL";
WheelPhase["WHEEL_END"] = "WHEEL_END";
WheelPhase["MOMENTUM_WHEEL_START"] = "MOMENTUM_WHEEL_START";
WheelPhase["MOMENTUM_WHEEL"] = "MOMENTUM_WHEEL";
WheelPhase["MOMENTUM_WHEEL_CANCEL"] = "MOMENTUM_WHEEL_CANCEL";
WheelPhase["MOMENTUM_WHEEL_END"] = "MOMENTUM_WHEEL_END";
})(WheelPhase || (WheelPhase = {}));
var console = window.console;
var DELTA_MAX_ABS = 150; // the initial timeout period is pretty long, so even old mouses, which emit wheel events less often, can produce a continuous gesture
// the timeout is automatically adjusted during a gesture
var WILL_END_TIMEOUT_DEFAULT = 400;
var axes = ['x', 'y'];
var deltaProp = {
x: 'deltaX',
y: 'deltaY',
x: 'deltaX',
y: 'deltaY'
};
var defaults = {
preventWheelAction: 'all',
isDebug: process.env.NODE_ENV === 'development',
preventWheelAction: 'all',
isDebug: process.env.NODE_ENV === 'development'
};
var WheelAnalyzer = /** @class */ (function () {
function WheelAnalyzer(options) {
var _this = this;
if (options === void 0) { options = {}; }
this.isStarted = false;
this.isMomentum = false;
this.lastAbsDelta = Infinity;
this.axisDeltas = [0, 0];
this.axisVelocity = [0, 0];
this.accelerationFactors = [];
this.deltaVelocity = 0; // px per second
this.deltaTotal = 0; // moved during this scroll interaction
/**
* @description merged scrollPoints
*/
this.scrollPoints = [];
this.scrollPointsToMerge = [];
this.subscriptions = [];
this.targets = [];
this.willEnd = this.end;
this.observe = function (target) {
target.addEventListener('wheel', _this.feedWheel, { passive: false });
_this.targets.push(target);
return _this.unobserve.bind(_this, target);
};
this.unobserve = function (target) {
target.removeEventListener('wheel', _this.feedWheel);
_this.targets = _this.targets.filter(function (t) { return t !== target; });
};
// stops watching all of its target elements for visibility changes.
this.disconnect = function () {
_this.targets.forEach(_this.unobserve);
};
this.subscribe = function (callback) {
_this.subscriptions.push(callback);
// return bound unsubscribe
return _this.unsubscribe.bind(_this, callback);
};
this.unsubscribe = function (callback) {
if (!callback)
throw new Error('please pass the callback which was used to subscribe');
_this.subscriptions = _this.subscriptions.filter(function (s) { return s !== callback; });
};
this.feedWheel = function (wheelEvents) {
if (!wheelEvents)
return;
if (Array.isArray(wheelEvents)) {
wheelEvents.forEach(function (wheelEvent) { return _this.processWheelEventData(wheelEvent); });
}
else {
_this.processWheelEventData(wheelEvents);
}
};
this.publish = function (phase, data) {
if (data === void 0) { data = _this.getCurrentState(phase); }
_this.subscriptions.forEach(function (fn) { return fn(phase, data); });
};
this.willEnd = debounce(99, function () { return _this.end(); });
// merge passed options with defaults (filter undefined option values)
this.options = Object.entries(options)
.filter(function (_a) {
var value = _a[1];
return value !== undefined;
})
.reduce(function (o, _a) {
var _b;
var key = _a[0], value = _a[1];
return Object.assign(o, (_b = {}, _b[key] = value, _b));
}, __assign({}, defaults));
var WheelAnalyzer = /*#__PURE__*/function () {
function WheelAnalyzer(options) {
var _this = this;
if (options === void 0) {
options = {};
}
WheelAnalyzer.prototype.shouldPreventDefault = function (e) {
var preventWheelAction = this.options.preventWheelAction;
var deltaX = e.deltaX, deltaY = e.deltaY;
switch (preventWheelAction) {
case 'all':
return true;
case 'x':
return Math.abs(deltaX) >= Math.abs(deltaY);
case 'y':
return Math.abs(deltaY) >= Math.abs(deltaX);
}
this.debugMessage('unsupported preventWheelAction value: ' + preventWheelAction, 'warn');
this.isStarted = false;
this.isStartPublished = false;
this.isMomentum = false;
this.lastAbsDelta = Infinity;
this.axisDeltas = [0, 0];
this.axisVelocity = [0, 0];
this.accelerationFactors = [];
this.scrollPoints = [];
this.scrollPointsToMerge = [];
this.subscriptions = [];
this.targets = [];
this.willEndTimeout = WILL_END_TIMEOUT_DEFAULT;
this.willEnd = function () {
var willEndId = setTimeout(function () {}, _this.willEndTimeout);
return function () {
clearTimeout(willEndId);
willEndId = setTimeout(_this.end, _this.willEndTimeout);
};
}();
this.observe = function (target) {
target.addEventListener('wheel', _this.feedWheel, {
passive: false
});
_this.targets.push(target);
return _this.unobserve.bind(_this, target);
};
WheelAnalyzer.prototype.processWheelEventData = function (e) {
if (e.deltaMode !== 0) {
if (this.options.isDebug) {
this.debugMessage('deltaMode is not 0');
}
return;
}
if (e.preventDefault && this.shouldPreventDefault(e)) {
e.preventDefault();
}
if (!this.isStarted) {
this.start();
}
var currentDelta = Math.abs(e.deltaY) > Math.abs(e.deltaX) ? e.deltaY : e.deltaX;
var currentAbsDelta = Math.abs(currentDelta);
if (this.isMomentum && currentAbsDelta > this.lastAbsDelta) {
this.end();
this.start();
}
this.axisDeltas = this.axisDeltas.map(function (delta, i) { return delta + e[deltaProp[axes[i]]]; });
this.deltaTotal = this.deltaTotal + currentDelta;
this.lastAbsDelta = currentAbsDelta;
this.scrollPointsToMerge.push({
currentDelta: currentDelta,
currentAbsDelta: currentAbsDelta,
axisDelta: [e.deltaX, e.deltaY],
timestamp: e.timeStamp || Date.now(),
});
if (this.scrollPointsToMerge.length === WHEELEVENTS_TO_MERGE) {
var mergedScrollPoint = {
currentDelta: this.scrollPointsToMerge.reduce(function (sum, b) { return sum + b.currentDelta; }, 0) / WHEELEVENTS_TO_MERGE,
currentAbsDelta: this.scrollPointsToMerge.reduce(function (sum, b) { return sum + b.currentAbsDelta; }, 0) / WHEELEVENTS_TO_MERGE,
axisDelta: this.scrollPointsToMerge
.reduce(function (_a, _b) {
var sumX = _a[0], sumY = _a[1];
var _c = _b.axisDelta, x = _c[0], y = _c[1];
return [sumX + x, sumY + y];
}, [0, 0])
.map(function (sum) { return sum / WHEELEVENTS_TO_MERGE; }),
timestamp: this.scrollPointsToMerge.reduce(function (sum, b) { return sum + b.timestamp; }, 0) / WHEELEVENTS_TO_MERGE,
};
this.scrollPoints.push(mergedScrollPoint);
// only update velo after a merged scrollpoint was generated
this.updateVelocityNew();
if (!this.isMomentum) {
this.detectMomentum();
}
// reset merge array
this.scrollPointsToMerge = [];
}
this.publish(WheelPhase.ANY_WHEEL);
this.publish(this.isMomentum ? WheelPhase.MOMENTUM_WHEEL : WheelPhase.WHEEL);
// calc debounced end function, to recognize end of wheel event stream
this.willEnd();
this.unobserve = function (target) {
target.removeEventListener('wheel', _this.feedWheel);
_this.targets = _this.targets.filter(function (t) {
return t !== target;
});
}; // stops watching all of its target elements for visibility changes.
this.disconnect = function () {
_this.targets.forEach(_this.unobserve);
};
WheelAnalyzer.prototype.debugMessage = function (msg, level) {
if (level === void 0) { level = 'log'; }
if (!this.options.isDebug)
return;
console[level](msg);
this.subscribe = function (callback) {
_this.subscriptions.push(callback); // return bound unsubscribe
return _this.unsubscribe.bind(_this, callback);
};
WheelAnalyzer.prototype.updateVelocityNew = function () {
var _this = this;
// need to have two recent points to calc velocity
var _a = this.scrollPoints.slice(-2), pA = _a[0], pB = _a[1];
if (!pA || !pB) {
return;
}
// time delta
var deltaTime = pB.timestamp - pA.timestamp;
if (deltaTime <= 0) {
this.debugMessage('invalid deltaTime');
return;
}
// calc the velocity per axes
var velocity = pB.axisDelta.map(function (d) { return d / deltaTime; });
// calc the acceleration factor per axis
var accelerationFactor = velocity.map(function (v, i) {
return v / (_this.axisVelocity[i] || 1);
this.unsubscribe = function (callback) {
if (!callback) throw new Error('please pass the callback which was used to subscribe');
_this.subscriptions = _this.subscriptions.filter(function (s) {
return s !== callback;
});
};
this.feedWheel = function (wheelEvents) {
if (!wheelEvents) return;
if (Array.isArray(wheelEvents)) {
wheelEvents.forEach(function (wheelEvent) {
return _this.processWheelEventData(wheelEvent);
});
this.axisVelocity = velocity;
this.accelerationFactors.push(accelerationFactor);
} else {
_this.processWheelEventData(wheelEvents);
}
};
WheelAnalyzer.accelerationFactorInMomentumRange = function (accFactor) {
// when main axis is the the other one and there is no movement/change on the current one
if (accFactor === 0)
return true;
return accFactor <= ACC_FACTOR_MAX && accFactor >= ACC_FACTOR_MIN;
this.publish = function (phase, data) {
if (data === void 0) {
data = _this.getCurrentState(phase);
}
_this.subscriptions.forEach(function (fn) {
return fn(phase, data);
});
};
WheelAnalyzer.prototype.detectMomentum = function () {
if (this.accelerationFactors.length < WHEELEVENTS_TO_ANALAZE) {
return this.isMomentum;
this.end = function () {
if (!_this.isStarted) return;
if (_this.isMomentum) {
if (!_this.willEndSoon) {
_this.publish(WheelPhase.MOMENTUM_WHEEL_CANCEL);
} else {
_this.publish(WheelPhase.MOMENTUM_WHEEL_END);
}
var recentAccelerationFactors = this.accelerationFactors.slice(WHEELEVENTS_TO_ANALAZE * -1);
// check recent acceleration / deceleration factors
var detectedMomentum = recentAccelerationFactors.reduce(function (mightBeMomentum, accFac) {
// all recent need to match, if any did not match -> short circuit
if (!mightBeMomentum)
return false;
// when both axis decelerate exactly in the same rate it is very likely caused by momentum
var sameAccFac = !!accFac.reduce(function (f1, f2) { return (f1 && f1 < 1 && f1 === f2 ? 1 : 0); });
// check if acceleration factor is within momentum range
var bothAreInRangeOrZero = accFac.filter(WheelAnalyzer.accelerationFactorInMomentumRange).length === accFac.length;
// one the requirements must be fulfilled
return sameAccFac || bothAreInRangeOrZero;
}, true);
// only keep the most recent events
this.accelerationFactors = recentAccelerationFactors;
if (detectedMomentum && !this.isMomentum) {
this.publish(WheelPhase.WHEEL_END);
this.isMomentum = true;
this.publish(WheelPhase.MOMENTUM_WHEEL_START);
}
return this.isMomentum;
};
WheelAnalyzer.prototype.getDebugState = function () {
var props = __rest(this, []);
return props;
};
WheelAnalyzer.prototype.getCurrentState = function (type) {
var debugData = this.options.isDebug ? this.getDebugState() : null;
return {
type: type,
debugData: debugData,
willEndSoon: this.willEndSoon,
isMomentum: this.isMomentum,
deltaVelocity: this.deltaVelocity,
deltaTotal: this.deltaTotal,
axisDeltas: this.axisDeltas,
axisVelocity: this.axisVelocity,
};
};
WheelAnalyzer.prototype.start = function () {
this.isStarted = true;
this.isMomentum = false;
this.lastAbsDelta = Infinity;
this.axisDeltas = [0, 0];
this.axisVelocity = [0, 0];
this.deltaVelocity = 0;
this.deltaTotal = 0;
this.scrollPointsToMerge = [];
this.scrollPoints = [];
this.accelerationFactors = [];
this.publish(WheelPhase.ANY_WHEEL_START);
this.publish(WheelPhase.WHEEL_START);
};
WheelAnalyzer.prototype.end = function () {
if (this.isMomentum) {
if (!this.willEndSoon) {
this.publish(WheelPhase.MOMENTUM_WHEEL_CANCEL);
}
else {
this.publish(WheelPhase.MOMENTUM_WHEEL_END);
}
}
else {
// in case of momentum, this event was already triggered when the momentum was detected so we do not trigger it here
this.publish(WheelPhase.WHEEL_END);
}
this.publish(WheelPhase.ANY_WHEEL_END);
this.isMomentum = false;
this.isStarted = false;
};
Object.defineProperty(WheelAnalyzer.prototype, "willEndSoon", {
get: function () {
var absDeltas = this.scrollPoints
.slice(SOON_ENDING_WHEEL_COUNT * -1)
.map(function (_a) {
var currentAbsDelta = _a.currentAbsDelta;
return currentAbsDelta;
});
var absDeltaAverage = absDeltas.reduce(function (a, b) { return a + b; }, 0) / absDeltas.length;
return absDeltaAverage <= SOON_ENDING_THRESHOLD;
},
enumerable: true,
configurable: true
} else {
// in case of momentum, this event was already triggered when the momentum was detected so we do not trigger it here
_this.publish(WheelPhase.WHEEL_END);
}
_this.publish(WheelPhase.ANY_WHEEL_END);
_this.isMomentum = false;
_this.isStarted = false;
}; // merge passed options with defaults (filter undefined option values)
this.options = Object.entries(options).filter(function (_ref) {
var value = _ref[1];
return value !== undefined;
}).reduce(function (o, _ref2) {
var _Object$assign;
var key = _ref2[0],
value = _ref2[1];
return Object.assign(o, (_Object$assign = {}, _Object$assign[key] = value, _Object$assign));
}, _extends({}, defaults));
}
var _proto = WheelAnalyzer.prototype;
_proto.shouldPreventDefault = function shouldPreventDefault(e) {
var preventWheelAction = this.options.preventWheelAction;
var deltaX = e.deltaX,
deltaY = e.deltaY;
switch (preventWheelAction) {
case 'all':
return true;
case 'x':
return Math.abs(deltaX) >= Math.abs(deltaY);
case 'y':
return Math.abs(deltaY) >= Math.abs(deltaX);
}
this.debugMessage('unsupported preventWheelAction value: ' + preventWheelAction, 'warn');
};
_proto.clampDelta = function clampDelta(delta) {
return Math.min(DELTA_MAX_ABS, Math.max(-DELTA_MAX_ABS, delta));
};
_proto.processWheelEventData = function processWheelEventData(wheelEvent) {
var _this2 = this;
var normalizedWheel = normalizeWheel(wheelEvent);
if (wheelEvent.preventDefault && this.shouldPreventDefault(wheelEvent)) {
wheelEvent.preventDefault();
}
if (!this.isStarted) {
this.start();
}
var currentDelta = this.clampDelta(Math.abs(normalizedWheel.deltaY) > Math.abs(normalizedWheel.deltaX) ? normalizedWheel.deltaY : normalizedWheel.deltaX);
var currentAbsDelta = Math.abs(currentDelta);
if (this.isMomentum && currentAbsDelta > this.lastAbsDelta) {
this.end();
this.start();
}
this.axisDeltas = this.axisDeltas.map(function (prevDelta, i) {
return prevDelta + _this2.clampDelta(normalizedWheel[deltaProp[axes[i]]]);
});
return WheelAnalyzer;
}());
this.lastAbsDelta = currentAbsDelta;
this.scrollPointsToMerge.push({
currentDelta: currentDelta,
currentAbsDelta: currentAbsDelta,
axisDeltaUnclampt: [normalizedWheel.deltaX, normalizedWheel.deltaY],
timestamp: wheelEvent.timeStamp || Date.now()
});
function EventBus(_a) {
var events = _a.events;
var listeners = Object.fromEntries(events.map(function (eventName) { return [eventName, new Array()]; }));
function on(type, listener) {
listeners[type] = listeners[type].concat(listener);
return off.bind(undefined, type, listener);
if (this.scrollPointsToMerge.length === WHEELEVENTS_TO_MERGE) {
var mergedScrollPoint = {
currentDelta: this.scrollPointsToMerge.reduce(function (sum, b) {
return sum + b.currentDelta;
}, 0) / WHEELEVENTS_TO_MERGE,
currentAbsDelta: this.scrollPointsToMerge.reduce(function (sum, b) {
return sum + b.currentAbsDelta;
}, 0) / WHEELEVENTS_TO_MERGE,
axisDeltaUnclampt: this.scrollPointsToMerge.reduce(function (_ref3, _ref4) {
var sumX = _ref3[0],
sumY = _ref3[1];
var _ref4$axisDeltaUnclam = _ref4.axisDeltaUnclampt,
x = _ref4$axisDeltaUnclam[0],
y = _ref4$axisDeltaUnclam[1];
return [sumX + x, sumY + y];
}, [0, 0]),
// TODO: should one devide here or not?!
//.map((sum) => sum / WHEELEVENTS_TO_MERGE),
timestamp: this.scrollPointsToMerge.reduce(function (sum, b) {
return sum + b.timestamp;
}, 0) / WHEELEVENTS_TO_MERGE
};
this.scrollPoints.push(mergedScrollPoint); // only update velocity after a merged scrollpoint was generated
this.updateVelocity();
if (!this.isMomentum) {
this.detectMomentum();
} // reset merge array
this.scrollPointsToMerge = [];
}
function off(type, listener) {
listeners[type] = listeners[type].filter(function (l) { return l === listener; });
if (!this.scrollPoints.length) {
this.updateStartVelocity();
} // publish start after all data points have been updated
// TODO: check momentum afterwards
if (!this.isStartPublished) {
this.publish(WheelPhase.ANY_WHEEL_START);
this.publish(WheelPhase.WHEEL_START);
this.isStartPublished = true;
}
function dispatch(type) {
listeners[type].forEach(function (l) { return l(); });
this.publish(WheelPhase.ANY_WHEEL);
this.publish(this.isMomentum ? WheelPhase.MOMENTUM_WHEEL : WheelPhase.WHEEL); // calc debounced end function, to recognize end of wheel event stream
this.willEnd();
};
_proto.debugMessage = function debugMessage(msg, level) {
if (level === void 0) {
level = 'log';
}
return Object.freeze({
on: on,
off: off,
dispatch: dispatch,
if (!this.options.isDebug) return;
console[level](msg);
};
_proto.updateStartVelocity = function updateStartVelocity() {
var latestScrollPoint = this.scrollPointsToMerge[this.scrollPointsToMerge.length - 1];
this.axisVelocity = latestScrollPoint.axisDeltaUnclampt.map(function (d) {
return d / WILL_END_TIMEOUT_DEFAULT;
});
}
};
var defaults$1 = {
axis: 'all',
};
function WheelGestures(_a) {
var axis = (_a === void 0 ? defaults$1 : _a).axis;
var _b = new WheelAnalyzer({
preventWheelAction: axis,
}), observe = _b.observe, unobserve = _b.unobserve, disconnect = _b.disconnect;
var on = EventBus({ events: ['wheelpan'] }).on;
on('wheelpan', function () { return undefined; });
return Object.freeze({
observe: observe,
unobserve: unobserve,
disconnect: disconnect,
on: on,
_proto.updateVelocity = function updateVelocity() {
var _this3 = this;
// need to have two recent points to calc velocity
var _this$scrollPoints$sl = this.scrollPoints.slice(-2),
pA = _this$scrollPoints$sl[0],
pB = _this$scrollPoints$sl[1];
if (!pA || !pB) {
return;
} // time delta
var deltaTime = pB.timestamp - pA.timestamp;
if (deltaTime <= 0) {
this.debugMessage('invalid deltaTime');
return;
} // calc the velocity per axes
var velocity = pB.axisDeltaUnclampt.map(function (d) {
return d / deltaTime;
}); // calc the acceleration factor per axis
var accelerationFactor = velocity.map(function (v, i) {
return v / (_this3.axisVelocity[i] || 1);
});
this.axisVelocity = velocity;
this.accelerationFactors.push(accelerationFactor);
this.updateWillEndTimeout(deltaTime);
};
_proto.updateWillEndTimeout = function updateWillEndTimeout(deltaTime) {
// use current time between events rounded up and increased by a bit as timeout
var newTimeout = Math.ceil(deltaTime / 10) * 10 * 1.2; // double the timeout, when momentum was not detected yet
if (!this.isMomentum) {
newTimeout = Math.max(100, newTimeout * 2);
}
this.willEndTimeout = Math.min(1000, Math.round(newTimeout));
};
WheelAnalyzer.accelerationFactorInMomentumRange = function accelerationFactorInMomentumRange(accFactor) {
// when main axis is the the other one and there is no movement/change on the current one
if (accFactor === 0) return true;
return accFactor <= ACC_FACTOR_MAX && accFactor >= ACC_FACTOR_MIN;
};
_proto.detectMomentum = function detectMomentum() {
if (this.accelerationFactors.length < WHEELEVENTS_TO_ANALAZE) {
return this.isMomentum;
}
var recentAccelerationFactors = this.accelerationFactors.slice(WHEELEVENTS_TO_ANALAZE * -1); // check recent acceleration / deceleration factors
var detectedMomentum = recentAccelerationFactors.reduce(function (mightBeMomentum, accFac) {
// all recent need to match, if any did not match -> short circuit
if (!mightBeMomentum) return false; // when both axis decelerate exactly in the same rate it is very likely caused by momentum
var sameAccFac = !!accFac.reduce(function (f1, f2) {
return f1 && f1 < 1 && f1 === f2 ? 1 : 0;
}); // check if acceleration factor is within momentum range
var bothAreInRangeOrZero = accFac.filter(WheelAnalyzer.accelerationFactorInMomentumRange).length === accFac.length; // one the requirements must be fulfilled
return sameAccFac || bothAreInRangeOrZero;
}, true); // only keep the most recent events
this.accelerationFactors = recentAccelerationFactors;
if (detectedMomentum && !this.isMomentum) {
this.publish(WheelPhase.WHEEL_END);
this.isMomentum = true;
this.publish(WheelPhase.MOMENTUM_WHEEL_START);
}
return this.isMomentum;
};
_proto.getDebugState = function getDebugState() {
var props = _extends({}, this);
return props;
};
_proto.getCurrentState = function getCurrentState(type) {
var debugData = this.options.isDebug ? this.getDebugState() : null;
return {
type: type,
debugData: debugData,
willEndSoon: this.willEndSoon,
isMomentum: this.isMomentum,
axisDeltas: this.axisDeltas,
axisVelocity: this.axisVelocity
};
};
_proto.start = function start() {
this.isStarted = true;
this.isStartPublished = false;
this.isMomentum = false;
this.lastAbsDelta = Infinity;
this.axisDeltas = [0, 0];
this.axisVelocity = [0, 0];
this.scrollPointsToMerge = [];
this.scrollPoints = [];
this.accelerationFactors = [];
this.willEndTimeout = WILL_END_TIMEOUT_DEFAULT;
};
_createClass(WheelAnalyzer, [{
key: "willEndSoon",
get: function get() {
var absDeltas = this.scrollPoints.slice(SOON_ENDING_WHEEL_COUNT * -1).map(function (_ref5) {
var currentAbsDelta = _ref5.currentAbsDelta;
return currentAbsDelta;
});
var absDeltaAverage = absDeltas.reduce(function (a, b) {
return a + b;
}, 0) / absDeltas.length;
return absDeltaAverage <= SOON_ENDING_THRESHOLD;
}
}]);
return WheelAnalyzer;
}();
function EventBus(_temp) {
var _ref = _temp === void 0 ? {} : _temp;
_objectDestructuringEmpty(_ref);
var listeners = {};
function on(type, listener) {
listeners[type] = (listeners[type] || []).concat(listener);
return function () {
return off(type, listener);
};
}
function off(type, listener) {
listeners[type] = (listeners[type] || []).filter(function (l) {
return l !== listener;
});
}
function dispatch(type, data) {
if (!(type in listeners)) return;
listeners[type].forEach(function (l) {
return l(data);
});
}
return Object.freeze({
on: on,
off: off,
dispatch: dispatch
});
}
export { WheelAnalyzer, WheelGestures, WheelPhase };
var WheelReason;
(function (WheelReason) {
WheelReason["USER"] = "USER";
WheelReason["ANY"] = "ANY";
})(WheelReason || (WheelReason = {}));
var _wheelType;
var wheelType = (_wheelType = {}, _wheelType[WheelReason.USER] = {
start: WheelPhase.WHEEL_START,
wheel: WheelPhase.WHEEL,
end: WheelPhase.WHEEL_END
}, _wheelType[WheelReason.ANY] = {
start: WheelPhase.ANY_WHEEL_START,
wheel: WheelPhase.ANY_WHEEL,
end: WheelPhase.ANY_WHEEL_END
}, _wheelType);
function WheelGestures(_temp) {
var _ref = _temp === void 0 ? {} : _temp,
_ref$axis = _ref.axis,
axis = _ref$axis === void 0 ? 'all' : _ref$axis,
_ref$wheelReason = _ref.wheelReason,
wheelReason = _ref$wheelReason === void 0 ? WheelReason.USER : _ref$wheelReason;
var dragState = {
down: false,
delta: [0, 0],
axisVelocity: [0, 0]
};
var wheelAnalyzer = new WheelAnalyzer({
preventWheelAction: axis
});
var observe = wheelAnalyzer.observe,
unobserve = wheelAnalyzer.unobserve,
disconnect = wheelAnalyzer.disconnect;
var _EventBus = EventBus(),
on = _EventBus.on,
off = _EventBus.off,
dispatch = _EventBus.dispatch;
wheelAnalyzer.subscribe(function (type, data) {
dragState = {
down: true,
// TODO: why * -1, should this not better be in analyzer or when used?
delta: data.axisDeltas.map(function (d) {
return d * -1;
}),
axisVelocity: [data.axisVelocity[0] * -1, data.axisVelocity[1] * -1]
};
switch (type) {
case wheelType[wheelReason].start:
dragState = _extends({}, dragState, {
down: true
});
dispatch('wheelstart', dragState);
break;
case wheelType[wheelReason].wheel:
dragState = _extends({}, dragState, {
down: true
});
dispatch('wheelmove', dragState);
break;
case wheelType[wheelReason].end:
dragState = _extends({}, dragState, {
down: false
});
dispatch('wheelend', dragState);
break;
default:
return;
}
});
return Object.freeze({
observe: observe,
unobserve: unobserve,
disconnect: disconnect,
on: on,
off: off
});
}
export { WheelAnalyzer, WheelGestures, WheelPhase, WheelReason };
//# sourceMappingURL=wheel-gestures.esm.js.map
{
"name": "wheel-gestures",
"main": "dist/wheel-gestures.cjs.js",
"version": "1.0.2-beta.3",
"description": "wheel gestures and momentum detection",
"main": "dist/index.js",
"module": "dist/wheel-gestures.esm.js",
"types": "dist/wheel-gestures.d.ts",
"version": "1.0.1",
"description": "wheel gestures and momentum detection",
"typings": "dist/index.d.ts",
"files": [
"dist"
],
"engines": {
"node": ">=10"
},
"scripts": {
"build": "rollup -c",
"dev": "rollup -c -w",
"start": "yarn dev",
"test": "react-scripts test",
"semantic-release": "semantic-release",
"link-examples": "yarn unlink; yarn link; cd examples; yarn link wheel-gestures;"
"start": "tsdx watch",
"build": "tsdx build",
"test": "tsdx test",
"lint": "tsdx lint",
"prepare": "tsdx build",
"semantic-release": "semantic-release"
},
"husky": {
"hooks": {
"pre-commit": "tsdx lint"
}
},
"repository": {

@@ -34,23 +45,13 @@ "type": "git",

"homepage": "https://github.com/xiel/wheel-gestures#readme",
"dependencies": {
"throttle-debounce": "^2.1.0"
},
"files": [
"dist/**/*",
"!**/test/*"
],
"peerDependencies": {},
"dependencies": {},
"devDependencies": {
"@testing-library/react": "^9.0.1",
"@types/jest": "^24.0.11",
"@types/throttle-debounce": "^2.1.0",
"eslint-config-prettier": "*",
"eslint-plugin-prettier": "*",
"eslint-plugin-react-app": "*",
"prettier": "^1.17.0",
"react-scripts": "^3.2.0",
"rollup": "^1.19.3",
"rollup-plugin-typescript2": "^0.24.0",
"tslib": "^1.9.3",
"typescript": "3.6.2",
"semantic-release": "^15.13.24"
"@testing-library/react": "^10.0.2",
"@types/jest": "^25.2.1",
"bundlewatch": "^0.2.6",
"husky": "^4.2.5",
"tsdx": "^0.13.2",
"tslib": "^1.11.1",
"typescript": "^3.8.3",
"semantic-release": "^17.0.4"
},

@@ -65,3 +66,11 @@ "jest": {

]
},
"bundlewatch": {
"files": [
{
"path": "dist/*.js",
"maxSize": "10kB"
}
]
}
}

@@ -5,2 +5,4 @@ # ![wheel gestures](./WheelGestures.svg)

🚧 `IN DEVELOPMENT` still testing and doing heaps of breaking changes, don't use yet please :)
[![npm (tag)](https://img.shields.io/npm/v/wheel-gestures/latest.svg)](https://www.npmjs.com/package/wheel-gestures)

@@ -10,1 +12,8 @@ ![GitHub top language](https://img.shields.io/github/languages/top/xiel/wheel-gestures.svg)

you bring the wheel events, wheelAnalyzer returns wheel gestures & momentum information
**OS & Browsers**k
- Mac OS (Chrome, Firefox, Safari, Brave, Edge)
- Windows (testing needed & help appreciated)
- Linux (testing needed & help appreciated)

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc