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.2 to 1.0.3

dist/wheel-analyzer/state.d.ts

18

dist/test/helper/recordPhases.d.ts

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

import { WheelAnalyzer } from '../../wheel-analyzer/wheel-analyzer';
import { PhaseData, SubscribeFn, WheelEventData, WheelTypes } from '../../wheel-analyzer/wheel-analyzer-types';

@@ -15,10 +14,11 @@ export declare type Range = [number, number];

}): {
wheelAnalyzer: WheelAnalyzer;
allPhaseData: {
type: import("../../wheel-analyzer/wheel-analyzer-types").WheelPhase;
willEndSoon: boolean;
isMomentum: boolean;
axisMovement: number[];
axisVelocity: number[];
}[];
wheelAnalyzer: Readonly<{
observe: (target: EventTarget) => import("../../wheel-analyzer/wheel-analyzer-types").Unobserve;
unobserve: (target: EventTarget) => void;
disconnect: () => void;
subscribe: (callback: SubscribeFn) => import("../../wheel-analyzer/wheel-analyzer-types").Unsubscribe;
unsubscribe: (callback: SubscribeFn) => void;
feedWheel: (wheelEvents: WheelEventData | WheelEventData[]) => void;
}>;
allPhaseData: PhaseData[];
};

@@ -25,0 +25,0 @@ export declare function recordPhases(wheelEvents: WheelEventData[]): {

export declare function lastOf<T>(array: T[]): T;
export declare function firstOf<T>(array: T[]): T;
export declare function average(numbers: number[]): number;

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

import { WheelAnalyzer } from './wheel-analyzer';
export declare type Vector3D = number[];
export interface WheelAnalyzerState {
isStarted: boolean;
isStartPublished: boolean;
isMomentum: boolean;
lastAbsDelta: number;
axisMovement: Vector3D;
axisVelocity: Vector3D;
accelerationFactors: number[][];
scrollPoints: ScrollPoint[];
scrollPointsToMerge: ScrollPoint[];
willEndTimeout: number;
}
export interface PhaseData {
type: WheelPhase;
isMomentum: boolean;
willEndSoon: boolean;
axisMovement: Vector3D;
axisVelocity: Vector3D;
}
export interface ScrollPoint {

@@ -23,3 +42,2 @@ currentAbsDelta: number;

}
export declare type PhaseData = ReturnType<typeof WheelAnalyzer.prototype.getCurrentState>;
export declare type SubscribeFn = (type: WheelPhase, data: PhaseData) => void;

@@ -26,0 +44,0 @@ export declare type Unsubscribe = () => void;

@@ -1,20 +0,6 @@

import { PreventWheelActionType, SubscribeFn, Unobserve, Unsubscribe, WheelEventData, WheelPhase } from './wheel-analyzer-types';
import { PreventWheelActionType, SubscribeFn, Unobserve, Unsubscribe, WheelEventData } from './wheel-analyzer-types';
export interface Options {
preventWheelAction: PreventWheelActionType;
}
export declare class WheelAnalyzer {
private isStarted;
private isStartPublished;
private isMomentum;
private lastAbsDelta;
private axisMovement;
private axisVelocity;
private accelerationFactors;
private scrollPoints;
private scrollPointsToMerge;
private subscriptions;
private targets;
private options;
private willEndTimeout;
constructor(options?: Partial<Options>);
export declare function WheelAnalyzer(optionsParam?: Partial<Options>): Readonly<{
observe: (target: EventTarget) => Unobserve;

@@ -25,23 +11,3 @@ unobserve: (target: EventTarget) => void;

unsubscribe: (callback: SubscribeFn) => void;
private publish;
feedWheel: (wheelEvents: WheelEventData | WheelEventData[]) => void;
private shouldPreventDefault;
private clampDelta;
private processWheelEventData;
private updateStartVelocity;
private updateVelocity;
private updateWillEndTimeout;
private static accelerationFactorInMomentumRange;
private detectMomentum;
getCurrentState(type: WheelPhase): {
type: WheelPhase;
willEndSoon: boolean;
isMomentum: boolean;
axisMovement: number[];
axisVelocity: number[];
};
private start;
private willEnd;
private end;
private get willEndSoon();
}
}>;

@@ -5,18 +5,2 @@ 'use strict';

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);
}
}
function _createClass(Constructor, protoProps, staticProps) {
if (protoProps) _defineProperties(Constructor.prototype, protoProps);
if (staticProps) _defineProperties(Constructor, staticProps);
return Constructor;
}
function _extends() {

@@ -70,2 +54,8 @@ _extends = Object.assign || function (target) {

function average(numbers) {
return numbers.reduce(function (a, b) {
return a + b;
}) / numbers.length;
}
var LINE_HEIGHT = 16 * 1.125;

@@ -87,2 +77,22 @@ var PAGE_HEIGHT = typeof window !== 'undefined' && window.innerHeight || 800;

/**
* the timeout is automatically adjusted during a gesture
* the initial timeout period is pretty long, so even old mouses, which emit wheel events less often, can produce a continuous gesture
*/
var WILL_END_TIMEOUT_DEFAULT = 400;
function createWheelAnalyzerState() {
return {
isStarted: false,
isStartPublished: false,
isMomentum: false,
lastAbsDelta: Infinity,
axisMovement: [0, 0],
axisVelocity: [0, 0],
accelerationFactors: [],
scrollPoints: [],
scrollPointsToMerge: [],
willEndTimeout: WILL_END_TIMEOUT_DEFAULT
};
}
(function (WheelPhase) {

@@ -104,10 +114,3 @@ WheelPhase["ANY_WHEEL_START"] = "ANY_WHEEL_START";

var ACC_FACTOR_MAX = 0.96;
var DELTA_MAX_ABS = 150; // TODO: test next release
/**
* the timeout is automatically adjusted during a gesture
* the initial timeout period is pretty long, so even old mouses, which emit wheel events less often, can produce a continuous gesture
*/
var WILL_END_TIMEOUT_DEFAULT = 400;
var DELTA_MAX_ABS = 150;
var axes = ['x', 'y'];

@@ -124,125 +127,84 @@ var deltaProp = {

};
var WheelAnalyzer = /*#__PURE__*/function () {
function WheelAnalyzer(options) {
var _this = this;
function WheelAnalyzer(optionsParam) {
if (optionsParam === void 0) {
optionsParam = {};
}
if (options === void 0) {
options = {};
}
var state = createWheelAnalyzerState();
var subscriptions = [];
var targets = []; // merge passed options with defaults (filter undefined option values)
this.isStarted = false;
this.isStartPublished = false;
this.isMomentum = false;
this.lastAbsDelta = Infinity;
this.axisMovement = [0, 0];
this.axisVelocity = [0, 0];
this.accelerationFactors = [];
this.scrollPoints = [];
this.scrollPointsToMerge = [];
this.subscriptions = [];
this.targets = [];
this.willEndTimeout = WILL_END_TIMEOUT_DEFAULT;
var options = Object.entries(optionsParam).filter(function (_ref) {
var value = _ref[1];
return value !== undefined;
}).reduce(function (o, _ref2) {
var _Object$assign;
this.observe = function (target) {
// TODO: need to test if passive supported? might throw error otherwise in older browsers?
target.addEventListener('wheel', _this.feedWheel, {
passive: false
});
var key = _ref2[0],
value = _ref2[1];
return Object.assign(o, (_Object$assign = {}, _Object$assign[key] = value, _Object$assign));
}, _extends({}, defaults));
_this.targets.push(target);
return _this.unobserve.bind(_this, target);
var observe = function observe(target) {
target.addEventListener('wheel', feedWheel, {
passive: false
});
targets.push(target);
return function () {
return unobserve(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.
var unobserve = function unobserve(target) {
target.removeEventListener('wheel', feedWheel);
targets = 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);
};
var disconnect = function disconnect() {
targets.forEach(unobserve);
};
this.subscribe = function (callback) {
_this.subscriptions.push(callback); // return bound unsubscribe
var subscribe = function subscribe(callback) {
subscriptions.push(callback); // return bound unsubscribe
return _this.unsubscribe.bind(_this, callback);
return function () {
return unsubscribe(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;
});
var unsubscribe = function unsubscribe(callback) {
if (!callback) throw new Error('please pass the callback which was used to subscribe');
subscriptions = subscriptions.filter(function (s) {
return s !== callback;
});
};
var publish = function publish(type) {
var data = {
type: type,
willEndSoon: willEndSoon(),
isMomentum: state.isMomentum,
axisMovement: state.axisMovement,
axisVelocity: state.axisVelocity
};
subscriptions.forEach(function (fn) {
return fn(type, data);
});
};
this.publish = function (phase, data) {
if (data === void 0) {
data = _this.getCurrentState(phase);
}
_this.subscriptions.forEach(function (fn) {
return fn(phase, data);
var feedWheel = function feedWheel(wheelEvents) {
if (Array.isArray(wheelEvents)) {
wheelEvents.forEach(function (wheelEvent) {
return processWheelEventData(wheelEvent);
});
};
} else {
processWheelEventData(wheelEvents);
}
};
this.feedWheel = function (wheelEvents) {
if (Array.isArray(wheelEvents)) {
wheelEvents.forEach(function (wheelEvent) {
return _this.processWheelEventData(wheelEvent);
});
} else {
_this.processWheelEventData(wheelEvents);
}
};
this.willEnd = function () {
var willEndId;
return function () {
clearTimeout(willEndId);
willEndId = setTimeout(_this.end, _this.willEndTimeout);
};
}();
this.end = function () {
if (!_this.isStarted) return;
if (_this.isMomentum) {
if (!_this.willEndSoon) {
_this.publish(exports.WheelPhase.MOMENTUM_WHEEL_CANCEL);
} else {
_this.publish(exports.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(exports.WheelPhase.WHEEL_END);
}
_this.publish(exports.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 shouldPreventDefault = function shouldPreventDefault(e) {
var preventWheelAction = options.preventWheelAction;
var deltaX = e.deltaX,

@@ -265,32 +227,30 @@ deltaY = e.deltaY;

_proto.clampDelta = function clampDelta(delta) {
var 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 processWheelEventData = function processWheelEventData(wheelEvent) {
var normalizedWheel = normalizeWheel(wheelEvent);
if (wheelEvent.preventDefault && this.shouldPreventDefault(wheelEvent)) {
if (wheelEvent.preventDefault && shouldPreventDefault(wheelEvent)) {
wheelEvent.preventDefault();
}
if (!this.isStarted) {
this.start();
if (!state.isStarted) {
start();
}
var currentDelta = this.clampDelta(Math.abs(normalizedWheel.deltaY) > Math.abs(normalizedWheel.deltaX) ? normalizedWheel.deltaY : normalizedWheel.deltaX);
var currentDelta = 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();
if (state.isMomentum && currentAbsDelta > state.lastAbsDelta) {
end();
start();
}
this.axisMovement = this.axisMovement.map(function (prevDelta, i) {
return prevDelta + _this2.clampDelta(normalizedWheel[deltaProp[axes[i]]]);
state.axisMovement = state.axisMovement.map(function (prevDelta, i) {
return prevDelta + clampDelta(normalizedWheel[deltaProp[axes[i]]]);
});
this.lastAbsDelta = currentAbsDelta;
this.scrollPointsToMerge.push({
state.lastAbsDelta = currentAbsDelta;
state.scrollPointsToMerge.push({
currentAbsDelta: currentAbsDelta,

@@ -301,8 +261,10 @@ axisDeltaUnclampt: [normalizedWheel.deltaX, normalizedWheel.deltaY],

if (this.scrollPointsToMerge.length === WHEELEVENTS_TO_MERGE) {
if (state.scrollPointsToMerge.length === WHEELEVENTS_TO_MERGE) {
var _state = state,
scrollPointsToMerge = _state.scrollPointsToMerge;
var mergedScrollPoint = {
currentAbsDelta: this.scrollPointsToMerge.reduce(function (sum, b) {
return sum + b.currentAbsDelta;
}, 0) / WHEELEVENTS_TO_MERGE,
axisDeltaUnclampt: this.scrollPointsToMerge.reduce(function (_ref3, _ref4) {
currentAbsDelta: average(scrollPointsToMerge.map(function (b) {
return b.currentAbsDelta;
})),
axisDeltaUnclampt: scrollPointsToMerge.reduce(function (_ref3, _ref4) {
var sumX = _ref3[0],

@@ -315,49 +277,47 @@ sumY = _ref3[1];

}, [0, 0]),
timestamp: this.scrollPointsToMerge.reduce(function (sum, b) {
return sum + b.timestamp;
}, 0) / WHEELEVENTS_TO_MERGE
timestamp: average(scrollPointsToMerge.map(function (b) {
return b.timestamp;
}))
};
this.scrollPoints.push(mergedScrollPoint); // only update velocity after a merged scrollpoint was generated
state.scrollPoints.push(mergedScrollPoint); // only update velocity after a merged scrollpoint was generated
this.updateVelocity();
updateVelocity();
if (!this.isMomentum) {
this.detectMomentum();
if (!state.isMomentum) {
detectMomentum();
} // reset merge array
this.scrollPointsToMerge = [];
state.scrollPointsToMerge = [];
}
if (!this.scrollPoints.length) {
this.updateStartVelocity();
if (!state.scrollPoints.length) {
updateStartVelocity();
} // publish start after velocity etc. have been updated
if (!this.isStartPublished) {
this.publish(exports.WheelPhase.ANY_WHEEL_START);
this.publish(exports.WheelPhase.WHEEL_START);
this.isStartPublished = true;
if (!state.isStartPublished) {
publish(exports.WheelPhase.ANY_WHEEL_START);
publish(exports.WheelPhase.WHEEL_START);
state.isStartPublished = true;
}
this.publish(exports.WheelPhase.ANY_WHEEL);
this.publish(this.isMomentum ? exports.WheelPhase.MOMENTUM_WHEEL : exports.WheelPhase.WHEEL); // calc debounced end function, to recognize end of wheel event stream
publish(exports.WheelPhase.ANY_WHEEL);
publish(state.isMomentum ? exports.WheelPhase.MOMENTUM_WHEEL : exports.WheelPhase.WHEEL); // calc debounced end function, to recognize end of wheel event stream
this.willEnd();
willEnd();
};
_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 updateStartVelocity = function updateStartVelocity() {
var latestScrollPoint = state.scrollPointsToMerge[state.scrollPointsToMerge.length - 1];
state.axisVelocity = latestScrollPoint.axisDeltaUnclampt.map(function (d) {
return d / state.willEndTimeout;
});
};
_proto.updateVelocity = function updateVelocity() {
var _this3 = this;
var updateVelocity = function updateVelocity() {
// 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];
var _state$scrollPoints$s = state.scrollPoints.slice(-2),
pA = _state$scrollPoints$s[0],
pB = _state$scrollPoints$s[1];

@@ -382,21 +342,21 @@ if (!pA || !pB) {

var accelerationFactor = velocity.map(function (v, i) {
return v / (_this3.axisVelocity[i] || 1);
return v / (state.axisVelocity[i] || 1);
});
this.axisVelocity = velocity;
this.accelerationFactors.push(accelerationFactor);
this.updateWillEndTimeout(deltaTime);
state.axisVelocity = velocity;
state.accelerationFactors.push(accelerationFactor);
updateWillEndTimeout(deltaTime);
};
_proto.updateWillEndTimeout = function updateWillEndTimeout(deltaTime) {
var 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) {
if (!state.isMomentum) {
newTimeout = Math.max(100, newTimeout * 2);
}
this.willEndTimeout = Math.min(1000, Math.round(newTimeout));
state.willEndTimeout = Math.min(1000, Math.round(newTimeout));
};
WheelAnalyzer.accelerationFactorInMomentumRange = function accelerationFactorInMomentumRange(accFactor) {
var accelerationFactorInMomentumRange = function accelerationFactorInMomentumRange(accFactor) {
// when main axis is the the other one and there is no movement/change on the current one

@@ -407,8 +367,8 @@ if (accFactor === 0) return true;

_proto.detectMomentum = function detectMomentum() {
if (this.accelerationFactors.length < WHEELEVENTS_TO_ANALAZE) {
return this.isMomentum;
var detectMomentum = function detectMomentum() {
if (state.accelerationFactors.length < WHEELEVENTS_TO_ANALAZE) {
return state.isMomentum;
}
var recentAccelerationFactors = this.accelerationFactors.slice(WHEELEVENTS_TO_ANALAZE * -1); // check recent acceleration / deceleration factors
var recentAccelerationFactors = state.accelerationFactors.slice(WHEELEVENTS_TO_ANALAZE * -1); // check recent acceleration / deceleration factors

@@ -423,3 +383,3 @@ var detectedMomentum = recentAccelerationFactors.reduce(function (mightBeMomentum, accFac) {

var bothAreInRangeOrZero = accFac.filter(WheelAnalyzer.accelerationFactorInMomentumRange).length === accFac.length; // one the requirements must be fulfilled
var bothAreInRangeOrZero = accFac.filter(accelerationFactorInMomentumRange).length === accFac.length; // one the requirements must be fulfilled

@@ -429,53 +389,66 @@ return sameAccFac || bothAreInRangeOrZero;

this.accelerationFactors = recentAccelerationFactors;
state.accelerationFactors = recentAccelerationFactors;
if (detectedMomentum && !this.isMomentum) {
this.publish(exports.WheelPhase.WHEEL_END);
this.isMomentum = true;
this.publish(exports.WheelPhase.MOMENTUM_WHEEL_START);
if (detectedMomentum && !state.isMomentum) {
publish(exports.WheelPhase.WHEEL_END);
state.isMomentum = true;
publish(exports.WheelPhase.MOMENTUM_WHEEL_START);
}
return this.isMomentum;
return state.isMomentum;
};
_proto.getCurrentState = function getCurrentState(type) {
return {
type: type,
willEndSoon: this.willEndSoon,
isMomentum: this.isMomentum,
axisMovement: this.axisMovement,
axisVelocity: this.axisVelocity
var start = function start() {
state = createWheelAnalyzerState();
state.isStarted = true;
};
var willEnd = function () {
var willEndId;
return function () {
clearTimeout(willEndId);
willEndId = setTimeout(end, state.willEndTimeout);
};
}();
var end = function end() {
if (!state.isStarted) return;
if (state.isMomentum) {
if (!willEndSoon()) {
publish(exports.WheelPhase.MOMENTUM_WHEEL_CANCEL);
} else {
publish(exports.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
publish(exports.WheelPhase.WHEEL_END);
}
publish(exports.WheelPhase.ANY_WHEEL_END);
state.isMomentum = false;
state.isStarted = false;
};
_proto.start = function start() {
this.isStarted = true;
this.isStartPublished = false;
this.isMomentum = false;
this.lastAbsDelta = Infinity;
this.axisMovement = [0, 0];
this.axisVelocity = [0, 0];
this.scrollPointsToMerge = [];
this.scrollPoints = [];
this.accelerationFactors = [];
this.willEndTimeout = WILL_END_TIMEOUT_DEFAULT;
var willEndSoon = function willEndSoon() {
var absDeltas = state.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;
};
_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 Object.freeze({
observe: observe,
unobserve: unobserve,
disconnect: disconnect,
subscribe: subscribe,
unsubscribe: unsubscribe,
feedWheel: feedWheel
});
}
return WheelAnalyzer;
}();
(function (WheelReason) {

@@ -508,3 +481,3 @@ WheelReason["USER"] = "USER";

};
var wheelAnalyzer = new WheelAnalyzer({
var wheelAnalyzer = WheelAnalyzer({
preventWheelAction: axis

@@ -511,0 +484,0 @@ });

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

"use strict";function e(){return(e=Object.assign||function(e){for(var t=1;t<arguments.length;t++){var s=arguments[t];for(var i in s)Object.prototype.hasOwnProperty.call(s,i)&&(e[i]=s[i])}return e}).apply(this,arguments)}Object.defineProperty(exports,"__esModule",{value:!0});var t,s=[1,18,"undefined"!=typeof window&&window.innerHeight||800];(t=exports.WheelPhase||(exports.WheelPhase={})).ANY_WHEEL_START="ANY_WHEEL_START",t.ANY_WHEEL="ANY_WHEEL",t.ANY_WHEEL_END="ANY_WHEEL_END",t.WHEEL_START="WHEEL_START",t.WHEEL="WHEEL",t.WHEEL_END="WHEEL_END",t.MOMENTUM_WHEEL_START="MOMENTUM_WHEEL_START",t.MOMENTUM_WHEEL="MOMENTUM_WHEEL",t.MOMENTUM_WHEEL_CANCEL="MOMENTUM_WHEEL_CANCEL",t.MOMENTUM_WHEEL_END="MOMENTUM_WHEEL_END";var i,n,r=["x","y"],o={x:"deltaX",y:"deltaY"},a={preventWheelAction:"all"},l=function(){function t(t){var s,i=this;void 0===t&&(t={}),this.isStarted=!1,this.isStartPublished=!1,this.isMomentum=!1,this.lastAbsDelta=Infinity,this.axisMovement=[0,0],this.axisVelocity=[0,0],this.accelerationFactors=[],this.scrollPoints=[],this.scrollPointsToMerge=[],this.subscriptions=[],this.targets=[],this.willEndTimeout=400,this.observe=function(e){return e.addEventListener("wheel",i.feedWheel,{passive:!1}),i.targets.push(e),i.unobserve.bind(i,e)},this.unobserve=function(e){e.removeEventListener("wheel",i.feedWheel),i.targets=i.targets.filter((function(t){return t!==e}))},this.disconnect=function(){i.targets.forEach(i.unobserve)},this.subscribe=function(e){return i.subscriptions.push(e),i.unsubscribe.bind(i,e)},this.unsubscribe=function(e){if(!e)throw new Error("please pass the callback which was used to subscribe");i.subscriptions=i.subscriptions.filter((function(t){return t!==e}))},this.publish=function(e,t){void 0===t&&(t=i.getCurrentState(e)),i.subscriptions.forEach((function(s){return s(e,t)}))},this.feedWheel=function(e){Array.isArray(e)?e.forEach((function(e){return i.processWheelEventData(e)})):i.processWheelEventData(e)},this.willEnd=function(){clearTimeout(s),s=setTimeout(i.end,i.willEndTimeout)},this.end=function(){i.isStarted&&(i.publish(i.isMomentum?i.willEndSoon?exports.WheelPhase.MOMENTUM_WHEEL_END:exports.WheelPhase.MOMENTUM_WHEEL_CANCEL:exports.WheelPhase.WHEEL_END),i.publish(exports.WheelPhase.ANY_WHEEL_END),i.isMomentum=!1,i.isStarted=!1)},this.options=Object.entries(t).filter((function(e){return void 0!==e[1]})).reduce((function(e,t){var s;return Object.assign(e,((s={})[t[0]]=t[1],s))}),e({},a))}var i,n=t.prototype;return n.shouldPreventDefault=function(e){var t=e.deltaX,s=e.deltaY;switch(this.options.preventWheelAction){case"all":return!0;case"x":return Math.abs(t)>=Math.abs(s);case"y":return Math.abs(s)>=Math.abs(t)}},n.clampDelta=function(e){return Math.min(150,Math.max(-150,e))},n.processWheelEventData=function(e){var t,i=this,n={deltaX:(t=e).deltaX*s[t.deltaMode],deltaY:t.deltaY*s[t.deltaMode],deltaZ:(t.deltaZ||0)*s[t.deltaMode],deltaMode:0,timestamp:t.timeStamp};e.preventDefault&&this.shouldPreventDefault(e)&&e.preventDefault(),this.isStarted||this.start();var a=this.clampDelta(Math.abs(n.deltaY)>Math.abs(n.deltaX)?n.deltaY:n.deltaX),l=Math.abs(a);if(this.isMomentum&&l>this.lastAbsDelta&&(this.end(),this.start()),this.axisMovement=this.axisMovement.map((function(e,t){return e+i.clampDelta(n[o[r[t]]])})),this.lastAbsDelta=l,this.scrollPointsToMerge.push({currentAbsDelta:l,axisDeltaUnclampt:[n.deltaX,n.deltaY],timestamp:e.timeStamp}),2===this.scrollPointsToMerge.length){var h={currentAbsDelta:this.scrollPointsToMerge.reduce((function(e,t){return e+t.currentAbsDelta}),0)/2,axisDeltaUnclampt:this.scrollPointsToMerge.reduce((function(e,t){var s=t.axisDeltaUnclampt;return[e[0]+s[0],e[1]+s[1]]}),[0,0]),timestamp:this.scrollPointsToMerge.reduce((function(e,t){return e+t.timestamp}),0)/2};this.scrollPoints.push(h),this.updateVelocity(),this.isMomentum||this.detectMomentum(),this.scrollPointsToMerge=[]}this.scrollPoints.length||this.updateStartVelocity(),this.isStartPublished||(this.publish(exports.WheelPhase.ANY_WHEEL_START),this.publish(exports.WheelPhase.WHEEL_START),this.isStartPublished=!0),this.publish(exports.WheelPhase.ANY_WHEEL),this.publish(this.isMomentum?exports.WheelPhase.MOMENTUM_WHEEL:exports.WheelPhase.WHEEL),this.willEnd()},n.updateStartVelocity=function(){this.axisVelocity=this.scrollPointsToMerge[this.scrollPointsToMerge.length-1].axisDeltaUnclampt.map((function(e){return e/400}))},n.updateVelocity=function(){var e=this,t=this.scrollPoints.slice(-2),s=t[0],i=t[1];if(s&&i){var n=i.timestamp-s.timestamp;if(!(n<=0)){var r=i.axisDeltaUnclampt.map((function(e){return e/n})),o=r.map((function(t,s){return t/(e.axisVelocity[s]||1)}));this.axisVelocity=r,this.accelerationFactors.push(o),this.updateWillEndTimeout(n)}}},n.updateWillEndTimeout=function(e){var t=10*Math.ceil(e/10)*1.2;this.isMomentum||(t=Math.max(100,2*t)),this.willEndTimeout=Math.min(1e3,Math.round(t))},t.accelerationFactorInMomentumRange=function(e){return 0===e||e<=.96&&e>=.6},n.detectMomentum=function(){if(this.accelerationFactors.length<5)return this.isMomentum;var e=this.accelerationFactors.slice(-5),s=e.reduce((function(e,s){if(!e)return!1;var i=!!s.reduce((function(e,t){return e&&e<1&&e===t?1:0})),n=s.filter(t.accelerationFactorInMomentumRange).length===s.length;return i||n}),!0);return this.accelerationFactors=e,s&&!this.isMomentum&&(this.publish(exports.WheelPhase.WHEEL_END),this.isMomentum=!0,this.publish(exports.WheelPhase.MOMENTUM_WHEEL_START)),this.isMomentum},n.getCurrentState=function(e){return{type:e,willEndSoon:this.willEndSoon,isMomentum:this.isMomentum,axisMovement:this.axisMovement,axisVelocity:this.axisVelocity}},n.start=function(){this.isStarted=!0,this.isStartPublished=!1,this.isMomentum=!1,this.lastAbsDelta=Infinity,this.axisMovement=[0,0],this.axisVelocity=[0,0],this.scrollPointsToMerge=[],this.scrollPoints=[],this.accelerationFactors=[],this.willEndTimeout=400},(i=[{key:"willEndSoon",get:function(){var e=this.scrollPoints.slice(-3).map((function(e){return e.currentAbsDelta}));return e.reduce((function(e,t){return e+t}),0)/e.length<=1.4}}])&&function(e,t){for(var s=0;s<t.length;s++){var i=t[s];i.enumerable=i.enumerable||!1,i.configurable=!0,"value"in i&&(i.writable=!0),Object.defineProperty(e,i.key,i)}}(t.prototype,i),t}();(i=exports.WheelReason||(exports.WheelReason={})).USER="USER",i.ANY="ANY";var h=((n={})[exports.WheelReason.USER]={start:exports.WheelPhase.WHEEL_START,wheel:exports.WheelPhase.WHEEL,end:exports.WheelPhase.WHEEL_END},n[exports.WheelReason.ANY]={start:exports.WheelPhase.ANY_WHEEL_START,wheel:exports.WheelPhase.ANY_WHEEL,end:exports.WheelPhase.ANY_WHEEL_END},n);exports.WheelAnalyzer=l,exports.WheelGestures=function(t){var s=void 0===t?{}:t,i=s.axis,n=s.wheelReason,r=void 0===n?exports.WheelReason.USER:n,o={down:!1,axisMovement:[0,0],axisVelocity:[0,0]},a=new l({preventWheelAction:void 0===i?"all":i}),u=a.observe,c=a.unobserve,E=a.disconnect,d=function(){var e={};function t(t,s){e[t]=(e[t]||[]).filter((function(e){return e!==s}))}return Object.freeze({on:function(s,i){return e[s]=(e[s]||[]).concat(i),function(){return t(s,i)}},off:t,dispatch:function(t,s){t in e&&e[t].forEach((function(e){return e(s)}))}})}(),p=d.on,f=d.off,m=d.dispatch;return a.subscribe((function(t,s){switch(o={down:!0,axisMovement:s.axisMovement.map((function(e){return-1*e})),axisVelocity:[-1*s.axisVelocity[0],-1*s.axisVelocity[1]]},t){case h[r].start:o=e({},o,{down:!0}),m("wheelstart",o);break;case h[r].wheel:o=e({},o,{down:!0}),m("wheelmove",o);break;case h[r].end:o=e({},o,{down:!1}),m("wheelend",o);break;default:return}})),Object.freeze({observe:u,unobserve:c,disconnect:E,on:p,off:f})};
"use strict";function e(){return(e=Object.assign||function(e){for(var t=1;t<arguments.length;t++){var n=arguments[t];for(var r in n)Object.prototype.hasOwnProperty.call(n,r)&&(e[r]=n[r])}return e}).apply(this,arguments)}function t(e){return e.reduce((function(e,t){return e+t}))/e.length}Object.defineProperty(exports,"__esModule",{value:!0});var n,r=[1,18,"undefined"!=typeof window&&window.innerHeight||800];(n=exports.WheelPhase||(exports.WheelPhase={})).ANY_WHEEL_START="ANY_WHEEL_START",n.ANY_WHEEL="ANY_WHEEL",n.ANY_WHEEL_END="ANY_WHEEL_END",n.WHEEL_START="WHEEL_START",n.WHEEL="WHEEL",n.WHEEL_END="WHEEL_END",n.MOMENTUM_WHEEL_START="MOMENTUM_WHEEL_START",n.MOMENTUM_WHEEL="MOMENTUM_WHEEL",n.MOMENTUM_WHEEL_CANCEL="MOMENTUM_WHEEL_CANCEL",n.MOMENTUM_WHEEL_END="MOMENTUM_WHEEL_END";var o,s,a=["x","y"],i={x:"deltaX",y:"deltaY"},l={preventWheelAction:"all"};function c(n){void 0===n&&(n={});var o,s={isStarted:!1,isStartPublished:!1,isMomentum:!1,lastAbsDelta:Infinity,axisMovement:[0,0],axisVelocity:[0,0],accelerationFactors:[],scrollPoints:[],scrollPointsToMerge:[],willEndTimeout:400},c=[],u=[],E=Object.entries(n).filter((function(e){return void 0!==e[1]})).reduce((function(e,t){var n;return Object.assign(e,((n={})[t[0]]=t[1],n))}),e({},l)),h=function(e){e.removeEventListener("wheel",m),u=u.filter((function(t){return t!==e}))},f=function(e){if(!e)throw new Error("please pass the callback which was used to subscribe");c=c.filter((function(t){return t!==e}))},M=function(e){var t={type:e,willEndSoon:N(),isMomentum:s.isMomentum,axisMovement:s.axisMovement,axisVelocity:s.axisVelocity};c.forEach((function(n){return n(e,t)}))},m=function(e){Array.isArray(e)?e.forEach((function(e){return p(e)})):p(e)},d=function(e){return Math.min(150,Math.max(-150,e))},p=function(e){var n,o={deltaX:(n=e).deltaX*r[n.deltaMode],deltaY:n.deltaY*r[n.deltaMode],deltaZ:(n.deltaZ||0)*r[n.deltaMode],deltaMode:0,timestamp:n.timeStamp};e.preventDefault&&function(e){var t=e.deltaX,n=e.deltaY;switch(E.preventWheelAction){case"all":return!0;case"x":return Math.abs(t)>=Math.abs(n);case"y":return Math.abs(n)>=Math.abs(t)}}(e)&&e.preventDefault(),s.isStarted||b();var l=d(Math.abs(o.deltaY)>Math.abs(o.deltaX)?o.deltaY:o.deltaX),c=Math.abs(l);if(s.isMomentum&&c>s.lastAbsDelta&&(L(),b()),s.axisMovement=s.axisMovement.map((function(e,t){return e+d(o[i[a[t]]])})),s.lastAbsDelta=c,s.scrollPointsToMerge.push({currentAbsDelta:c,axisDeltaUnclampt:[o.deltaX,o.deltaY],timestamp:e.timeStamp}),2===s.scrollPointsToMerge.length){var u=s.scrollPointsToMerge,h={currentAbsDelta:t(u.map((function(e){return e.currentAbsDelta}))),axisDeltaUnclampt:u.reduce((function(e,t){var n=t.axisDeltaUnclampt;return[e[0]+n[0],e[1]+n[1]]}),[0,0]),timestamp:t(u.map((function(e){return e.timestamp})))};s.scrollPoints.push(h),x(),s.isMomentum||T(),s.scrollPointsToMerge=[]}s.scrollPoints.length||W(),s.isStartPublished||(M(exports.WheelPhase.ANY_WHEEL_START),M(exports.WheelPhase.WHEEL_START),s.isStartPublished=!0),M(exports.WheelPhase.ANY_WHEEL),M(s.isMomentum?exports.WheelPhase.MOMENTUM_WHEEL:exports.WheelPhase.WHEEL),A()},W=function(){s.axisVelocity=s.scrollPointsToMerge[s.scrollPointsToMerge.length-1].axisDeltaUnclampt.map((function(e){return e/s.willEndTimeout}))},x=function(){var e=s.scrollPoints.slice(-2),t=e[0],n=e[1];if(t&&n){var r=n.timestamp-t.timestamp;if(!(r<=0)){var o=n.axisDeltaUnclampt.map((function(e){return e/r})),a=o.map((function(e,t){return e/(s.axisVelocity[t]||1)}));s.axisVelocity=o,s.accelerationFactors.push(a),v(r)}}},v=function(e){var t=10*Math.ceil(e/10)*1.2;s.isMomentum||(t=Math.max(100,2*t)),s.willEndTimeout=Math.min(1e3,Math.round(t))},_=function(e){return 0===e||e<=.96&&e>=.6},T=function(){if(s.accelerationFactors.length<5)return s.isMomentum;var e=s.accelerationFactors.slice(-5),t=e.reduce((function(e,t){if(!e)return!1;var n=!!t.reduce((function(e,t){return e&&e<1&&e===t?1:0})),r=t.filter(_).length===t.length;return n||r}),!0);return s.accelerationFactors=e,t&&!s.isMomentum&&(M(exports.WheelPhase.WHEEL_END),s.isMomentum=!0,M(exports.WheelPhase.MOMENTUM_WHEEL_START)),s.isMomentum},b=function(){(s={isStarted:!1,isStartPublished:!1,isMomentum:!1,lastAbsDelta:Infinity,axisMovement:[0,0],axisVelocity:[0,0],accelerationFactors:[],scrollPoints:[],scrollPointsToMerge:[],willEndTimeout:400}).isStarted=!0},A=function(){clearTimeout(o),o=setTimeout(L,s.willEndTimeout)},L=function(){s.isStarted&&(s.isMomentum?N()?M(exports.WheelPhase.MOMENTUM_WHEEL_END):M(exports.WheelPhase.MOMENTUM_WHEEL_CANCEL):M(exports.WheelPhase.WHEEL_END),M(exports.WheelPhase.ANY_WHEEL_END),s.isMomentum=!1,s.isStarted=!1)},N=function(){var e=s.scrollPoints.slice(-3).map((function(e){return e.currentAbsDelta}));return e.reduce((function(e,t){return e+t}),0)/e.length<=1.4};return Object.freeze({observe:function(e){return e.addEventListener("wheel",m,{passive:!1}),u.push(e),function(){return h(e)}},unobserve:h,disconnect:function(){u.forEach(h)},subscribe:function(e){return c.push(e),function(){return f(e)}},unsubscribe:f,feedWheel:m})}(o=exports.WheelReason||(exports.WheelReason={})).USER="USER",o.ANY="ANY";var u=((s={})[exports.WheelReason.USER]={start:exports.WheelPhase.WHEEL_START,wheel:exports.WheelPhase.WHEEL,end:exports.WheelPhase.WHEEL_END},s[exports.WheelReason.ANY]={start:exports.WheelPhase.ANY_WHEEL_START,wheel:exports.WheelPhase.ANY_WHEEL,end:exports.WheelPhase.ANY_WHEEL_END},s);exports.WheelAnalyzer=c,exports.WheelGestures=function(t){var n=void 0===t?{}:t,r=n.axis,o=n.wheelReason,s=void 0===o?exports.WheelReason.USER:o,a={down:!1,axisMovement:[0,0],axisVelocity:[0,0]},i=c({preventWheelAction:void 0===r?"all":r}),l=i.observe,E=i.unobserve,h=i.disconnect,f=function(){var e={};function t(t,n){e[t]=(e[t]||[]).filter((function(e){return e!==n}))}return Object.freeze({on:function(n,r){return e[n]=(e[n]||[]).concat(r),function(){return t(n,r)}},off:t,dispatch:function(t,n){t in e&&e[t].forEach((function(e){return e(n)}))}})}(),M=f.on,m=f.off,d=f.dispatch;return i.subscribe((function(t,n){switch(a={down:!0,axisMovement:n.axisMovement.map((function(e){return-1*e})),axisVelocity:[-1*n.axisVelocity[0],-1*n.axisVelocity[1]]},t){case u[s].start:a=e({},a,{down:!0}),d("wheelstart",a);break;case u[s].wheel:a=e({},a,{down:!0}),d("wheelmove",a);break;case u[s].end:a=e({},a,{down:!1}),d("wheelend",a);break;default:return}})),Object.freeze({observe:l,unobserve:E,disconnect:h,on:M,off:m})};
//# sourceMappingURL=wheel-gestures.cjs.production.min.js.map

@@ -1,17 +0,1 @@

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);
}
}
function _createClass(Constructor, protoProps, staticProps) {
if (protoProps) _defineProperties(Constructor.prototype, protoProps);
if (staticProps) _defineProperties(Constructor, staticProps);
return Constructor;
}
function _extends() {

@@ -65,2 +49,8 @@ _extends = Object.assign || function (target) {

function average(numbers) {
return numbers.reduce(function (a, b) {
return a + b;
}) / numbers.length;
}
var LINE_HEIGHT = 16 * 1.125;

@@ -82,2 +72,22 @@ var PAGE_HEIGHT = typeof window !== 'undefined' && window.innerHeight || 800;

/**
* the timeout is automatically adjusted during a gesture
* the initial timeout period is pretty long, so even old mouses, which emit wheel events less often, can produce a continuous gesture
*/
var WILL_END_TIMEOUT_DEFAULT = 400;
function createWheelAnalyzerState() {
return {
isStarted: false,
isStartPublished: false,
isMomentum: false,
lastAbsDelta: Infinity,
axisMovement: [0, 0],
axisVelocity: [0, 0],
accelerationFactors: [],
scrollPoints: [],
scrollPointsToMerge: [],
willEndTimeout: WILL_END_TIMEOUT_DEFAULT
};
}
var WheelPhase;

@@ -101,10 +111,3 @@

var ACC_FACTOR_MAX = 0.96;
var DELTA_MAX_ABS = 150; // TODO: test next release
/**
* the timeout is automatically adjusted during a gesture
* the initial timeout period is pretty long, so even old mouses, which emit wheel events less often, can produce a continuous gesture
*/
var WILL_END_TIMEOUT_DEFAULT = 400;
var DELTA_MAX_ABS = 150;
var axes = ['x', 'y'];

@@ -122,125 +125,84 @@ var deltaProp = {

};
var WheelAnalyzer = /*#__PURE__*/function () {
function WheelAnalyzer(options) {
var _this = this;
function WheelAnalyzer(optionsParam) {
if (optionsParam === void 0) {
optionsParam = {};
}
if (options === void 0) {
options = {};
}
var state = createWheelAnalyzerState();
var subscriptions = [];
var targets = []; // merge passed options with defaults (filter undefined option values)
this.isStarted = false;
this.isStartPublished = false;
this.isMomentum = false;
this.lastAbsDelta = Infinity;
this.axisMovement = [0, 0];
this.axisVelocity = [0, 0];
this.accelerationFactors = [];
this.scrollPoints = [];
this.scrollPointsToMerge = [];
this.subscriptions = [];
this.targets = [];
this.willEndTimeout = WILL_END_TIMEOUT_DEFAULT;
var options = Object.entries(optionsParam).filter(function (_ref) {
var value = _ref[1];
return value !== undefined;
}).reduce(function (o, _ref2) {
var _Object$assign;
this.observe = function (target) {
// TODO: need to test if passive supported? might throw error otherwise in older browsers?
target.addEventListener('wheel', _this.feedWheel, {
passive: false
});
var key = _ref2[0],
value = _ref2[1];
return Object.assign(o, (_Object$assign = {}, _Object$assign[key] = value, _Object$assign));
}, _extends({}, defaults));
_this.targets.push(target);
return _this.unobserve.bind(_this, target);
var observe = function observe(target) {
target.addEventListener('wheel', feedWheel, {
passive: false
});
targets.push(target);
return function () {
return unobserve(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.
var unobserve = function unobserve(target) {
target.removeEventListener('wheel', feedWheel);
targets = 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);
};
var disconnect = function disconnect() {
targets.forEach(unobserve);
};
this.subscribe = function (callback) {
_this.subscriptions.push(callback); // return bound unsubscribe
var subscribe = function subscribe(callback) {
subscriptions.push(callback); // return bound unsubscribe
return _this.unsubscribe.bind(_this, callback);
return function () {
return unsubscribe(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;
});
var unsubscribe = function unsubscribe(callback) {
if (!callback) throw new Error('please pass the callback which was used to subscribe');
subscriptions = subscriptions.filter(function (s) {
return s !== callback;
});
};
var publish = function publish(type) {
var data = {
type: type,
willEndSoon: willEndSoon(),
isMomentum: state.isMomentum,
axisMovement: state.axisMovement,
axisVelocity: state.axisVelocity
};
subscriptions.forEach(function (fn) {
return fn(type, data);
});
};
this.publish = function (phase, data) {
if (data === void 0) {
data = _this.getCurrentState(phase);
}
_this.subscriptions.forEach(function (fn) {
return fn(phase, data);
var feedWheel = function feedWheel(wheelEvents) {
if (Array.isArray(wheelEvents)) {
wheelEvents.forEach(function (wheelEvent) {
return processWheelEventData(wheelEvent);
});
};
} else {
processWheelEventData(wheelEvents);
}
};
this.feedWheel = function (wheelEvents) {
if (Array.isArray(wheelEvents)) {
wheelEvents.forEach(function (wheelEvent) {
return _this.processWheelEventData(wheelEvent);
});
} else {
_this.processWheelEventData(wheelEvents);
}
};
this.willEnd = function () {
var willEndId;
return function () {
clearTimeout(willEndId);
willEndId = setTimeout(_this.end, _this.willEndTimeout);
};
}();
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);
}
} 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 shouldPreventDefault = function shouldPreventDefault(e) {
var preventWheelAction = options.preventWheelAction;
var deltaX = e.deltaX,

@@ -263,32 +225,30 @@ deltaY = e.deltaY;

_proto.clampDelta = function clampDelta(delta) {
var 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 processWheelEventData = function processWheelEventData(wheelEvent) {
var normalizedWheel = normalizeWheel(wheelEvent);
if (wheelEvent.preventDefault && this.shouldPreventDefault(wheelEvent)) {
if (wheelEvent.preventDefault && shouldPreventDefault(wheelEvent)) {
wheelEvent.preventDefault();
}
if (!this.isStarted) {
this.start();
if (!state.isStarted) {
start();
}
var currentDelta = this.clampDelta(Math.abs(normalizedWheel.deltaY) > Math.abs(normalizedWheel.deltaX) ? normalizedWheel.deltaY : normalizedWheel.deltaX);
var currentDelta = 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();
if (state.isMomentum && currentAbsDelta > state.lastAbsDelta) {
end();
start();
}
this.axisMovement = this.axisMovement.map(function (prevDelta, i) {
return prevDelta + _this2.clampDelta(normalizedWheel[deltaProp[axes[i]]]);
state.axisMovement = state.axisMovement.map(function (prevDelta, i) {
return prevDelta + clampDelta(normalizedWheel[deltaProp[axes[i]]]);
});
this.lastAbsDelta = currentAbsDelta;
this.scrollPointsToMerge.push({
state.lastAbsDelta = currentAbsDelta;
state.scrollPointsToMerge.push({
currentAbsDelta: currentAbsDelta,

@@ -299,8 +259,10 @@ axisDeltaUnclampt: [normalizedWheel.deltaX, normalizedWheel.deltaY],

if (this.scrollPointsToMerge.length === WHEELEVENTS_TO_MERGE) {
if (state.scrollPointsToMerge.length === WHEELEVENTS_TO_MERGE) {
var _state = state,
scrollPointsToMerge = _state.scrollPointsToMerge;
var mergedScrollPoint = {
currentAbsDelta: this.scrollPointsToMerge.reduce(function (sum, b) {
return sum + b.currentAbsDelta;
}, 0) / WHEELEVENTS_TO_MERGE,
axisDeltaUnclampt: this.scrollPointsToMerge.reduce(function (_ref3, _ref4) {
currentAbsDelta: average(scrollPointsToMerge.map(function (b) {
return b.currentAbsDelta;
})),
axisDeltaUnclampt: scrollPointsToMerge.reduce(function (_ref3, _ref4) {
var sumX = _ref3[0],

@@ -313,49 +275,47 @@ sumY = _ref3[1];

}, [0, 0]),
timestamp: this.scrollPointsToMerge.reduce(function (sum, b) {
return sum + b.timestamp;
}, 0) / WHEELEVENTS_TO_MERGE
timestamp: average(scrollPointsToMerge.map(function (b) {
return b.timestamp;
}))
};
this.scrollPoints.push(mergedScrollPoint); // only update velocity after a merged scrollpoint was generated
state.scrollPoints.push(mergedScrollPoint); // only update velocity after a merged scrollpoint was generated
this.updateVelocity();
updateVelocity();
if (!this.isMomentum) {
this.detectMomentum();
if (!state.isMomentum) {
detectMomentum();
} // reset merge array
this.scrollPointsToMerge = [];
state.scrollPointsToMerge = [];
}
if (!this.scrollPoints.length) {
this.updateStartVelocity();
if (!state.scrollPoints.length) {
updateStartVelocity();
} // publish start after velocity etc. have been updated
if (!this.isStartPublished) {
this.publish(WheelPhase.ANY_WHEEL_START);
this.publish(WheelPhase.WHEEL_START);
this.isStartPublished = true;
if (!state.isStartPublished) {
publish(WheelPhase.ANY_WHEEL_START);
publish(WheelPhase.WHEEL_START);
state.isStartPublished = true;
}
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
publish(WheelPhase.ANY_WHEEL);
publish(state.isMomentum ? WheelPhase.MOMENTUM_WHEEL : WheelPhase.WHEEL); // calc debounced end function, to recognize end of wheel event stream
this.willEnd();
willEnd();
};
_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 updateStartVelocity = function updateStartVelocity() {
var latestScrollPoint = state.scrollPointsToMerge[state.scrollPointsToMerge.length - 1];
state.axisVelocity = latestScrollPoint.axisDeltaUnclampt.map(function (d) {
return d / state.willEndTimeout;
});
};
_proto.updateVelocity = function updateVelocity() {
var _this3 = this;
var updateVelocity = function updateVelocity() {
// 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];
var _state$scrollPoints$s = state.scrollPoints.slice(-2),
pA = _state$scrollPoints$s[0],
pB = _state$scrollPoints$s[1];

@@ -380,21 +340,21 @@ if (!pA || !pB) {

var accelerationFactor = velocity.map(function (v, i) {
return v / (_this3.axisVelocity[i] || 1);
return v / (state.axisVelocity[i] || 1);
});
this.axisVelocity = velocity;
this.accelerationFactors.push(accelerationFactor);
this.updateWillEndTimeout(deltaTime);
state.axisVelocity = velocity;
state.accelerationFactors.push(accelerationFactor);
updateWillEndTimeout(deltaTime);
};
_proto.updateWillEndTimeout = function updateWillEndTimeout(deltaTime) {
var 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) {
if (!state.isMomentum) {
newTimeout = Math.max(100, newTimeout * 2);
}
this.willEndTimeout = Math.min(1000, Math.round(newTimeout));
state.willEndTimeout = Math.min(1000, Math.round(newTimeout));
};
WheelAnalyzer.accelerationFactorInMomentumRange = function accelerationFactorInMomentumRange(accFactor) {
var accelerationFactorInMomentumRange = function accelerationFactorInMomentumRange(accFactor) {
// when main axis is the the other one and there is no movement/change on the current one

@@ -405,8 +365,8 @@ if (accFactor === 0) return true;

_proto.detectMomentum = function detectMomentum() {
if (this.accelerationFactors.length < WHEELEVENTS_TO_ANALAZE) {
return this.isMomentum;
var detectMomentum = function detectMomentum() {
if (state.accelerationFactors.length < WHEELEVENTS_TO_ANALAZE) {
return state.isMomentum;
}
var recentAccelerationFactors = this.accelerationFactors.slice(WHEELEVENTS_TO_ANALAZE * -1); // check recent acceleration / deceleration factors
var recentAccelerationFactors = state.accelerationFactors.slice(WHEELEVENTS_TO_ANALAZE * -1); // check recent acceleration / deceleration factors

@@ -421,3 +381,3 @@ var detectedMomentum = recentAccelerationFactors.reduce(function (mightBeMomentum, accFac) {

var bothAreInRangeOrZero = accFac.filter(WheelAnalyzer.accelerationFactorInMomentumRange).length === accFac.length; // one the requirements must be fulfilled
var bothAreInRangeOrZero = accFac.filter(accelerationFactorInMomentumRange).length === accFac.length; // one the requirements must be fulfilled

@@ -427,53 +387,66 @@ return sameAccFac || bothAreInRangeOrZero;

this.accelerationFactors = recentAccelerationFactors;
state.accelerationFactors = recentAccelerationFactors;
if (detectedMomentum && !this.isMomentum) {
this.publish(WheelPhase.WHEEL_END);
this.isMomentum = true;
this.publish(WheelPhase.MOMENTUM_WHEEL_START);
if (detectedMomentum && !state.isMomentum) {
publish(WheelPhase.WHEEL_END);
state.isMomentum = true;
publish(WheelPhase.MOMENTUM_WHEEL_START);
}
return this.isMomentum;
return state.isMomentum;
};
_proto.getCurrentState = function getCurrentState(type) {
return {
type: type,
willEndSoon: this.willEndSoon,
isMomentum: this.isMomentum,
axisMovement: this.axisMovement,
axisVelocity: this.axisVelocity
var start = function start() {
state = createWheelAnalyzerState();
state.isStarted = true;
};
var willEnd = function () {
var willEndId;
return function () {
clearTimeout(willEndId);
willEndId = setTimeout(end, state.willEndTimeout);
};
}();
var end = function end() {
if (!state.isStarted) return;
if (state.isMomentum) {
if (!willEndSoon()) {
publish(WheelPhase.MOMENTUM_WHEEL_CANCEL);
} else {
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
publish(WheelPhase.WHEEL_END);
}
publish(WheelPhase.ANY_WHEEL_END);
state.isMomentum = false;
state.isStarted = false;
};
_proto.start = function start() {
this.isStarted = true;
this.isStartPublished = false;
this.isMomentum = false;
this.lastAbsDelta = Infinity;
this.axisMovement = [0, 0];
this.axisVelocity = [0, 0];
this.scrollPointsToMerge = [];
this.scrollPoints = [];
this.accelerationFactors = [];
this.willEndTimeout = WILL_END_TIMEOUT_DEFAULT;
var willEndSoon = function willEndSoon() {
var absDeltas = state.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;
};
_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 Object.freeze({
observe: observe,
unobserve: unobserve,
disconnect: disconnect,
subscribe: subscribe,
unsubscribe: unsubscribe,
feedWheel: feedWheel
});
}
return WheelAnalyzer;
}();
var WheelReason;

@@ -508,3 +481,3 @@

};
var wheelAnalyzer = new WheelAnalyzer({
var wheelAnalyzer = WheelAnalyzer({
preventWheelAction: axis

@@ -511,0 +484,0 @@ });

{
"name": "wheel-gestures",
"version": "1.0.2",
"version": "1.0.3",
"description": "wheel gestures and momentum detection",

@@ -5,0 +5,0 @@ "main": "dist/index.js",

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

- Mac OS (Chrome, Firefox, Safari, Brave, Edge)
- Mac OS (Chrome, Firefox, Safari, Brave, Edge, IE10+)
- Windows (testing needed & help appreciated)
- Linux (testing needed & help appreciated)

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

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