New Research: Supply Chain Attack on Axios Pulls Malicious Dependency from npm.Details →
Socket
Book a DemoSign in
Socket

vert

Package Overview
Dependencies
Maintainers
1
Versions
3
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

vert - npm Package Compare versions

Comparing version
0.1.0
to
0.2.0
.browserslistrc

Sorry, the diff of this file is not supported yet

+11
root = true
[*]
indent_style = space
indent_size = 2
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true
end_of_line = lf
# editorconfig-tools is unable to ignore longs strings or urls
max_line_length = null
{
"extends": "airbnb-base",
"env": {
"browser": true
}
}
const presets = [
[
"@babel/env",
{
useBuiltIns: "usage",
},
],
];
module.exports = { presets };
var vert=function(n){var t={};function r(e){if(t[e])return t[e].exports;var u=t[e]={i:e,l:!1,exports:{}};return n[e].call(u.exports,u,u.exports,r),u.l=!0,u.exports}return r.m=n,r.c=t,r.d=function(n,t,e){r.o(n,t)||Object.defineProperty(n,t,{enumerable:!0,get:e})},r.r=function(n){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(n,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(n,"__esModule",{value:!0})},r.t=function(n,t){if(1&t&&(n=r(n)),8&t)return n;if(4&t&&"object"==typeof n&&n&&n.__esModule)return n;var e=Object.create(null);if(r.r(e),Object.defineProperty(e,"default",{enumerable:!0,value:n}),2&t&&"string"!=typeof n)for(var u in n)r.d(e,u,function(t){return n[t]}.bind(null,u));return e},r.n=function(n){var t=n&&n.__esModule?function(){return n.default}:function(){return n};return r.d(t,"a",t),t},r.o=function(n,t){return Object.prototype.hasOwnProperty.call(n,t)},r.p="",r(r.s=0)}([function(n,t,r){"use strict";r.r(t);var e={UP:"UP",DOWN:"DOWN",LEFT:"LEFT",RIGHT:"RIGHT"},u={x:"undefined"!=typeof window?window.pageXOffset:0,y:"undefined"!=typeof window?window.pageYOffset:0},o=function(){return u},i=e.DOWN,c=function(n){i=n},f=function(){return i},l=[],d=function(n){return n<.5?2*n*n:(4-2*n)*n-1},a=function(n,t){var r,e=1e3,u=o()[n],i=t,c=0;"x"===n?c=document.body.scrollWidth-document.documentElement.clientWidth:"y"===n&&(c=document.body.scrollHeight-document.documentElement.clientHeight),t>c?i=c:t<0&&(i=0),l.push(function(t,o){r||(r=t,e+=t);var c=(t-r)/(e-r);c<=1&&c>=0?"x"===n?window.scrollTo({left:u+(i-u)*d(c)}):"y"===n&&window.scrollTo({top:u+(i-u)*d(c)}):l.splice(o,1)})},y={x:function(n){return a("x",n)},y:function(n){return a("y",n)}},s=null,p=null,w=null,m=[],x=function n(t){var r,i,f=!1,d=!1;l.forEach(function(n,r){return n(t,r)}),r=window.pageXOffset,i=window.pageYOffset,u.x=r,u.y=i,o().x<p?(f=!0,c(e.LEFT)):o().x>p&&(f=!0,c(e.RIGHT)),o().y<w?(d=!0,c(e.UP)):o().y>w&&(d=!0,c(e.DOWN)),m.forEach(function(n){(f&&n.xCondition||d&&n.yCondition)&&n.callback()}),p=o().x,w=o().y,s=window.requestAnimationFrame(n)},v=function(){s=window.requestAnimationFrame(x)},b=function(){return window.cancelAnimationFrame(s)},O=function(n,t,r){var u=Date.now();return m.push({id:u,xCondition:n,yCondition:t,callback:function(){var u=n&&n(o().x),i=t&&t(o().y);if(n&&t)return u&&i?void r(o(),f()):(f()!==e.LEFT&&f()!==e.RIGHT||u&&r(o(),f()),void(f()!==e.UP&&f()!==e.DOWN||i&&r(o(),f())));u&&r(o(),f()),i&&r(o(),f())}}),function(){m.splice(m.map(function(n){return n.id}).indexOf(u),1)}},g=function(){return!0},T=function(n){return function(t){return t<n}},h=function(n){var t=!1;return function(r){return t?r<=n&&(t=!1,!0):r>=n&&(t=!0)}},E=function(n){return function(t){return t>n}},P=function(n,t){return function(r){return r>n&&r<t}},j={x:{any:function(n){return O(g,null,n)},lt:function(n,t){return O(T(n),null,t)},eq:function(n,t){return O(h(n),null,t)},gt:function(n,t){return O(E(n),null,t)},between:function(n,t,r){return O(P(n,t),null,r)},custom:function(n,t){return O(n,null,t)}},y:{any:function(n){return O(null,g,n)},lt:function(n,t){return O(null,T(n),t)},eq:function(n,t){return O(null,h(n),t)},gt:function(n,t){return O(null,E(n),t)},between:function(n,t,r){return O(null,P(n,t),r)},custom:function(n,t){return O(null,n,t)}},xy:{any:function(n){return O(g,g,n)},custom:function(n,t,r){return O(n,t,r)}}};r.d(t,"x",function(){return D}),r.d(t,"y",function(){return F}),r.d(t,"xy",function(){return W}),r.d(t,"DIRECTIONS",function(){return e}),r.d(t,"start",function(){return v}),r.d(t,"stop",function(){return b}),r.d(t,"animate",function(){return y}),r.d(t,"coords",function(){return o}),r.d(t,"direction",function(){return f});var D=j.x,F=j.y,W=j.xy}]);
MIT License
Copyright (c) 2019 Christian McCormick
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
# vert (beta)
![npm](https://img.shields.io/npm/v/vert.svg)
![npm bundle size (minified)](https://img.shields.io/bundlephobia/min/vert.svg)
A minimal, super simple browser scroll library with a convenient set of easy-to-use listeners and animate methods. Vert is optimized using requestAnimationFrame and provides the ability to start/stop itself and remove listeners for added performance tuning.
Please note that this library is still in beta and small issues may arise. If you come across any bugs, please create a new issue and describe your problem in detail along with a sample of the code that causes the bug. Thanks and enjoy!
## Install
```
npm install vert --save
```
## Usage
Before setting up any listeners, vert must first be started.
```
vert.start();
```
Now any of the provided listeners can be created. The following is a simple xy listener (listens for scroll events on the x and y axes) that will print the coordinates and scroll direction to the console anytime the user scrolls.
```
vert.xy.any((coords, direction) => {
console.log(`x: ${coords.x}, y: ${coords.y}, direction: ${direction}`);
});
```
Other listeners include lesser than (lt), equals (eq), greater than (gt), and custom listeners. Documentation for these can be found below.
To speed up performance you can stop vert when you don't need it. Simply run the following to stop listening to scroll events.
```
vert.stop();
```
If you need to start vert back up, you can run `vert.start()` again to do so.
## Documentation
### Coordinates and Scroll Direction
You can use the `vert.coords()` method to obtain the current scroll position at any time. The scroll position will be return as an object with x and y properties.
```
vert.coords(); // => { x: 0, y: 125 }
```
The last scroll direction can be obtained with `vert.direction()`. It will be either `vert.DIRECTIONS.UP`, `vert.DIRECTIONS.DOWN`, `vert.DIRECTIONS.LEFT`, or `vert.DIRECTIONS.RIGHT`.
```
vert.direction(); // => 'LEFT'
```
### Listeners
There are a handful of scroll event listeners available on the x and y axes, and a small subset available for both axes (xy). Each listener will fire a callback providing the current coordinates and scroll direction. The following list will explain how each listener works, and which axes it can be used on.
To cancel an event listener, you must first store its return value to a variable. You can then call it to cancel the listener.
```
var xListener = vert.x.any(() => {});
xListener();
```
#### any
*Axes: x, y and xy*
Fires on any scroll event.
```
// vert.x.any((coords, direction) => {});
// vert.y.any((coords, direction) => {});
// vert.xy.any((coords, direction) => {});
vert.x.any((coords, direction) => {
console.log(`x: ${coords.x}, y: ${coords.y}, direction: ${direction}`);
});
```
#### lt
*Axes: x and y*
Fires when the scroll position is less than the given value.
```
// vert.x.lt([value], (coords, direction) => {});
// vert.y.lt([value], (coords, direction) => {});
vert.y.lt(500, (coords, direction) => {
console.log(`x: ${coords.x}, y: ${coords.y}, direction: ${direction}`);
});
```
#### eq
*Axes: x and y*
Fires when the scroll position is equal to the given value. It will fire regardless of scroll direction.
```
// vert.x.eq([value], (coords, direction) => {});
// vert.y.eq([value], (coords, direction) => {});
vert.x.eq(350, (coords, direction) => {
console.log(`x: ${coords.x}, y: ${coords.y}, direction: ${direction}`);
});
```
#### gt
*Axes: x and y*
Fires when the scroll position is greater than the given value.
```
// vert.x.gt([value], (coords, direction) => {});
// vert.y.gt([value], (coords, direction) => {});
vert.y.gt(755, (coords, direction) => {
console.log(`x: ${coords.x}, y: ${coords.y}, direction: ${direction}`);
});
```
#### between
*Axes: x and y*
Fires when the scroll position is between the given values.
```
// vert.x.between([value1], [value2], (coords, direction) => {});
// vert.y.between([value1], [value2], (coords, direction) => {});
vert.x.between(200, 800, (coords, direction) => {
console.log(`x: ${coords.x}, y: ${coords.y}, direction: ${direction}`);
});
```
#### custom
*Axes: x, y, and xy*
Fires when the callbacks provided pass true for their respective axes.
```
// vert.x.between([xCondition], (coords, direction) => {});
// vert.y.between([yCondition], (coords, direction) => {});
// vert.xy.between([xCondition], [yCondition], (coords, direction) => {});
vert.xy.custom(
x => {
return x > 100;
},
y => {
return y < 500;
},
(coords, direction) => {
console.log(`x: ${coords.x}, y: ${coords.y}, direction: ${direction}`);
}
);
```
### Animate
You can animate the browser scroll position to any given coordinate on the x or y axis. Animating on both axes is currently not supported.
```
// vert.animate.x([value]);
// vert.animate.y([value]);
vert.animate.y(1000);
```
## Coming Soon
- [ ] xy animation support
- [ ] Cancellable animations (programmatic and on a new scroll event)
import { getCoords } from './coords';
const activeAnimations = [];
const easeInOutQuad = (t) => {
if (t < 0.5) {
return 2 * t * t;
}
return -1 + (4 - 2 * t) * t;
};
const animateOnAxis = (axis, value) => {
let start;
let duration = 1000;
const initialValue = getCoords()[axis];
let valueWithinBounds = value;
let axisDimension = 0;
if (axis === 'x') {
axisDimension = document.body.scrollWidth - document.documentElement.clientWidth;
} else if (axis === 'y') {
axisDimension = document.body.scrollHeight - document.documentElement.clientHeight;
}
if (value > axisDimension) {
valueWithinBounds = axisDimension;
} else if (value < 0) {
valueWithinBounds = 0;
}
activeAnimations.push((timestamp, i) => {
if (!start) {
start = timestamp;
duration += timestamp;
}
const time = (timestamp - start) / (duration - start);
if (time <= 1 && time >= 0) {
if (axis === 'x') {
window.scrollTo({
left: initialValue + (valueWithinBounds - initialValue) * easeInOutQuad(time),
});
} else if (axis === 'y') {
window.scrollTo({
top: initialValue + (valueWithinBounds - initialValue) * easeInOutQuad(time),
});
}
} else {
activeAnimations.splice(i, 1);
}
});
};
export const animate = {
x: value => animateOnAxis('x', value),
y: value => animateOnAxis('y', value),
};
export const animations = () => activeAnimations;
export const any = () => true;
export const lt = value => coord => coord < value;
export const eq = (value) => {
let fired = false;
return (coord) => {
if (fired) {
if (coord <= value) {
fired = false;
return true;
}
return false;
}
if (coord >= value) {
fired = true;
return fired;
}
return false;
};
};
export const gt = value => coord => coord > value;
export const between = (value1, value2) => coord => coord > value1 && coord < value2;
const currentCoords = {
x: typeof window !== 'undefined' ? window.pageXOffset : 0,
y: typeof window !== 'undefined' ? window.pageYOffset : 0,
};
export const setCoords = (x, y) => {
currentCoords.x = x;
currentCoords.y = y;
};
export const getCoords = () => currentCoords;
import { setCoords, getCoords } from './coords';
import { setDirection, getDirection } from './direction';
import DIRECTIONS from './directions';
import { animations } from './animate';
let requestAnimationFrameId = null;
let lastX = null;
let lastY = null;
const activeListeners = [];
const tick = function tick(timestamp) {
let xDiff = false;
let yDiff = false;
animations().forEach((_animation, i) => _animation(timestamp, i));
setCoords(window.pageXOffset, window.pageYOffset);
if (getCoords().x < lastX) {
xDiff = true;
setDirection(DIRECTIONS.LEFT);
} else if (getCoords().x > lastX) {
xDiff = true;
setDirection(DIRECTIONS.RIGHT);
}
if (getCoords().y < lastY) {
yDiff = true;
setDirection(DIRECTIONS.UP);
} else if (getCoords().y > lastY) {
yDiff = true;
setDirection(DIRECTIONS.DOWN);
}
activeListeners.forEach((listener) => {
if ((xDiff && listener.xCondition) || (yDiff && listener.yCondition)) {
listener.callback();
}
});
lastX = getCoords().x;
lastY = getCoords().y;
requestAnimationFrameId = window.requestAnimationFrame(tick);
};
export const start = () => {
requestAnimationFrameId = window.requestAnimationFrame(tick);
};
export const stop = () => window.cancelAnimationFrame(requestAnimationFrameId);
export const addListener = (xCondition, yCondition, callback) => {
const id = Date.now();
activeListeners.push({
id,
xCondition,
yCondition,
callback: () => {
const xConditionValid = xCondition && xCondition(getCoords().x);
const yConditionValid = yCondition && yCondition(getCoords().y);
// xy listeners
if (xCondition && yCondition) {
if (xConditionValid && yConditionValid) {
callback(getCoords(), getDirection());
// Prevent calling multiple callbacks for each valid condition
return;
}
/**
* Since this may be a custom xy listener with a condition for each axis,
* check the scroll direction first. This ensures that scrolling on the x axis
* will not trigger the y callback if it is false.
*/
if (getDirection() === DIRECTIONS.LEFT || getDirection() === DIRECTIONS.RIGHT) {
if (xConditionValid) {
callback(getCoords(), getDirection());
}
}
// Likewise, do the same check for the y axis
if (getDirection() === DIRECTIONS.UP || getDirection() === DIRECTIONS.DOWN) {
if (yConditionValid) {
callback(getCoords(), getDirection());
}
}
// Prevent further callbacks from being fired
return;
}
if (xConditionValid) {
callback(getCoords(), getDirection());
}
if (yConditionValid) {
callback(getCoords(), getDirection());
}
},
});
return () => {
activeListeners.splice(activeListeners.map(_listener => _listener.id).indexOf(id), 1);
};
};
import DIRECTIONS from './directions';
let direction = DIRECTIONS.DOWN;
export const setDirection = (newDirection) => {
direction = newDirection;
};
export const getDirection = () => direction;
const DIRECTIONS = {
UP: 'UP',
DOWN: 'DOWN',
LEFT: 'LEFT',
RIGHT: 'RIGHT',
};
export default DIRECTIONS;
import DIRECTIONS from './directions';
import { start, stop } from './core';
import { animate } from './animate';
import { getCoords } from './coords';
import { getDirection } from './direction';
import listeners from './listeners';
export {
DIRECTIONS,
start,
stop,
animate,
};
export { getCoords as coords };
export { getDirection as direction };
export const { x, y, xy } = listeners;
import { addListener } from './core';
import {
any,
lt,
eq,
gt,
between,
} from './conditions';
export default {
x: {
any: callback => addListener(any, null, callback),
lt: (value, callback) => addListener(lt(value), null, callback),
eq: (value, callback) => addListener(eq(value), null, callback),
gt: (value, callback) => addListener(gt(value), null, callback),
between: (value1, value2, callback) => addListener(between(value1, value2), null, callback),
custom: (condition, callback) => addListener(condition, null, callback),
},
y: {
any: callback => addListener(null, any, callback),
lt: (value, callback) => addListener(null, lt(value), callback),
eq: (value, callback) => addListener(null, eq(value), callback),
gt: (value, callback) => addListener(null, gt(value), callback),
between: (value1, value2, callback) => addListener(null, between(value1, value2), callback),
custom: (condition, callback) => addListener(null, condition, callback),
},
xy: {
any: callback => addListener(any, any, callback),
custom: (condition1, condition2, callback) => addListener(condition1, condition2, callback),
},
};
{
"env": {
"mocha": true
},
"rules": {
"no-unused-expressions": 0
}
}
import chai from 'chai';
import {
DIRECTIONS,
coords,
direction,
start,
stop,
animate,
x,
y,
xy,
} from '../src';
const { expect } = chai;
describe('DIRECTIONS', () => {
it('should be an object with LEFT, RIGHT, UP, and DOWN defined', () => {
expect(DIRECTIONS.LEFT).to.eq('LEFT');
expect(DIRECTIONS.RIGHT).to.eq('RIGHT');
expect(DIRECTIONS.UP).to.eq('UP');
expect(DIRECTIONS.DOWN).to.eq('DOWN');
});
});
describe('coords', () => {
it('should return an object with x and y properties defaulting to 0', () => {
expect(coords().x).to.eq(0);
expect(coords().y).to.eq(0);
});
});
describe('direction', () => {
it('should return a value with a default of DIRECTION.DOWN', () => {
expect(direction()).to.eq(DIRECTIONS.DOWN);
});
});
describe('start', () => {
it('should be a function', () => {
expect(start).to.be.a.instanceOf(Function);
});
});
describe('stop', () => {
it('should be a function', () => {
expect(stop).to.be.a.instanceOf(Function);
});
});
describe('animate', () => {
it('should be an object with x and y methods', () => {
expect(animate.x).to.be.a.instanceOf(Function);
expect(animate.y).to.be.a.instanceOf(Function);
});
});
describe('x', () => {
it('should be an object with any, lt, eq, gt, between, and custom methods', () => {
expect(x.any).to.be.instanceOf(Function);
expect(x.lt).to.be.instanceOf(Function);
expect(x.eq).to.be.instanceOf(Function);
expect(x.gt).to.be.instanceOf(Function);
expect(x.between).to.be.instanceOf(Function);
expect(x.custom).to.be.instanceOf(Function);
});
});
describe('y', () => {
it('should be an object with any, lt, eq, gt, between, and custom methods', () => {
expect(y.any).to.be.instanceOf(Function);
expect(y.lt).to.be.instanceOf(Function);
expect(y.eq).to.be.instanceOf(Function);
expect(y.gt).to.be.instanceOf(Function);
expect(y.between).to.be.instanceOf(Function);
expect(y.custom).to.be.instanceOf(Function);
});
});
describe('xy', () => {
it('should be an object with any and custom methods', () => {
expect(xy.any).to.be.instanceOf(Function);
expect(xy.custom).to.be.instanceOf(Function);
});
});
const path = require('path');
module.exports = {
entry: './src/index.js',
devServer: {
contentBase: './dist',
},
output: {
filename: 'vert.js',
path: path.resolve(__dirname, 'dist'),
library: 'vert',
},
module: {
rules: [
{
test: /\.m?js$/,
exclude: /(node_modules)/,
use: {
loader: 'babel-loader',
options: {
presets: ['@babel/preset-env'],
},
},
},
],
},
};
+32
-7
{
"name": "vert",
"version": "0.1.0",
"version": "0.2.0",
"description": "The swiss army knife of browser scrolling.",
"main": "index.js",
"keywords": [
"scroll",
"browser",
"dom",
"event",
"listener",
"animate"
],
"main": "src/index.js",
"scripts": {
"test": "node_modules/.bin/_mocha --compilers js:babel-core/register"
"test": "node_modules/.bin/_mocha --require @babel/register",
"watch": "npx webpack --config webpack.config.js --mode development -w",
"start": "webpack-dev-server --open --mode development",
"build": "npx webpack --config webpack.config.js --mode production"
},
"author": "Christian McCormick",
"license": "MIT",
"repository": "christianmccormick/vert",
"devDependencies": {
"babel-core": "^6.24.1",
"babel-preset-es2015": "^6.24.1",
"chai": "^3.5.0",
"mocha": "^3.2.0"
"@babel/cli": "^7.2.3",
"@babel/core": "^7.2.2",
"@babel/preset-env": "^7.3.1",
"@babel/register": "^7.0.0",
"babel-loader": "^8.0.5",
"chai": "^4.2.0",
"eslint": "^5.3.0",
"eslint-config-airbnb-base": "^13.1.0",
"eslint-plugin-import": "^2.15.0",
"eslint-plugin-mocha": "^5.2.1",
"mocha": "^5.2.0",
"webpack": "^4.29.0",
"webpack-cli": "^3.2.1",
"webpack-dev-server": "^3.1.14"
},
"dependencies": {
"@babel/polyfill": "^7.2.5"
}
}
-3
{
"presets": ["es2015"]
}

Sorry, the diff of this file is not supported yet

export default class Vert {
constructor() {}
}
import chai from 'chai';
import Vert from './../src/vert';
const expect = chai.expect;
describe('Vert', () => {
let vert;
beforeEach(() => {
vert = new Vert();
});
it('should be defined', () => {
expect(vert).to.not.be.undefined;
});
});