New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

react-easy-infinite-scroll-hook

Package Overview
Dependencies
Maintainers
1
Versions
79
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

react-easy-infinite-scroll-hook - npm Package Compare versions

Comparing version 1.8.7 to 1.9.0

2

dist/cjs/index.js

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

"use strict";Object.defineProperty(exports,"__esModule",{value:!0});var t,e,o=require("react");function l(t,e,o,l){return new(o||(o=Promise))((function(i,n){function r(t){try{c(l.next(t))}catch(t){n(t)}}function s(t){try{c(l.throw(t))}catch(t){n(t)}}function c(t){var e;t.done?i(t.value):(e=t.value,e instanceof o?e:new o((function(t){t(e)}))).then(r,s)}c((l=l.apply(t,e||[])).next())}))}exports.ScrollAxisName=void 0,(t=exports.ScrollAxisName||(exports.ScrollAxisName={})).VERTICAL="vertical",t.HORIZONTAL="horizontal",exports.ScrollDirection=void 0,(e=exports.ScrollDirection||(exports.ScrollDirection={})).UP="up",e.DOWN="down",e.LEFT="left",e.RIGHT="right";class i{constructor(t){this._validateScrollValue=(t,e,o)=>{const l=t<0?-1:1;return Math.abs(t)>e?null!=o?o:e*l:t},this._scroll=function({scrollTop:t,scrollLeft:e}){var o;if(!(null===(o=this._scrollingContainerRef)||void 0===o?void 0:o.scrollingElement))return;const{scrollHeight:l,scrollWidth:i}=this._scrollingContainerRef.scrollingElement;void 0!==t&&(this._scrollingContainerRef.scrollingElement.scrollTop=this._validateScrollValue(t,l)),void 0!==e&&(this._scrollingContainerRef.scrollingElement.scrollLeft=this._validateScrollValue(e,i))},this._computeThreshold=function(){const{state:{clientWidth:t,clientHeight:e},props:{scrollThreshold:o=1},_scrollingContainerRef:l}=this;if(!(null==l?void 0:l.scrollingElement)||t===l.scrollingElement.clientWidth&&e===l.scrollingElement.clientHeight)return;const{clientWidth:i,clientHeight:n,scrollHeight:r,scrollWidth:s}=l.scrollingElement;let c={vertical:0,horizontal:0};if("string"==typeof o){const t=Math.abs(parseInt(o));c={vertical:this._validateScrollValue(t,r,n),horizontal:this._validateScrollValue(t,s,i)}}else{const t=o>1?1:o<=0?.1:o;c={vertical:t*n,horizontal:t*i}}this.state.computedScrollThreshold=c,this.state.clientWidth=i,this.state.clientHeight=n},this._getPossibleDirections=function(){this._computeThreshold();const{state:{clientHeight:t,clientWidth:e,computedScrollThreshold:{vertical:o,horizontal:l}},props:{reverse:i={}},_scrollingContainerRef:n}=this,{scrollHeight:r,scrollWidth:s,scrollLeft:c,scrollTop:h}=n.scrollingElement,{column:a,row:u}=i,d=(t,e)=>Math.abs(t)<=e,p=(t,e,o,l)=>Math.abs(t)>=Math.abs(e-o-l);return{[a?exports.ScrollDirection.DOWN:exports.ScrollDirection.UP]:d(h,o),[a?exports.ScrollDirection.UP:exports.ScrollDirection.DOWN]:p(h,r,t,o),[u?exports.ScrollDirection.RIGHT:exports.ScrollDirection.LEFT]:d(c,l),[u?exports.ScrollDirection.LEFT:exports.ScrollDirection.RIGHT]:p(c,s,e,l)}},this._loadByDirection=function(t,e,o){return l(this,void 0,void 0,(function*(){const{state:{isLoading:l,thresholdReached:i},props:{next:n,hasMore:r}}=this,s=t===exports.ScrollDirection.UP?exports.ScrollAxisName.VERTICAL:exports.ScrollAxisName.HORIZONTAL;if(!l){const l=r[t]&&!i[t]&&o[t],c=!l&&r[e]&&!i[e]&&o[e];if(l||c)try{const o=l?t:e;this.state.thresholdReached[o]=!0,this.state.isLoading=!0,yield n(o)}finally{setTimeout((()=>this._onLoadComplete(s)),0)}}}))},this._checkOffsetAndLoadMore=function(){const{_scrollingContainerRef:t}=this;if(!t)return;const e=this._getPossibleDirections(),o=t=>{!e[t]&&this.state.thresholdReached[t]&&(this.state.thresholdReached[t]=!1)};Object.values(exports.ScrollDirection).forEach((t=>o(t))),this._loadByDirection(exports.ScrollDirection.UP,exports.ScrollDirection.DOWN,e),this._loadByDirection(exports.ScrollDirection.LEFT,exports.ScrollDirection.RIGHT,e)},this._setRef=function(t){var e,o,l;const i={scrollingElement:null,registerEventListener:null};if(this.props.windowScroll)i.scrollingElement=document.scrollingElement,i.registerEventListener=document;else{const n=null!==(l=null!==(e=null==t?void 0:t._scrollingContainer)&&void 0!==e?e:null===(o=null==t?void 0:t.Grid)||void 0===o?void 0:o._scrollingContainer)&&void 0!==l?l:t;i.scrollingElement=n,i.registerEventListener=n}const{scrollingElement:n,registerEventListener:r}=i;if(n&&r&&("number"!=typeof n.scrollHeight||"number"!=typeof n.scrollWidth||"number"!=typeof n.scrollLeft||"number"!=typeof n.scrollTop||"number"!=typeof n.clientHeight||"number"!=typeof n.clientWidth||"function"!=typeof r.addEventListener||"function"!=typeof r.removeEventListener)||!n||!r)return void console.error("Sorry I can't use this container - try using a different DOM element.");this._scrollingContainerRef=i;const s=()=>{var t;if(!(null===(t=this._scrollingContainerRef)||void 0===t?void 0:t.scrollingElement))return;const{_scrollingContainerRef:{scrollingElement:e},props:{onScroll:o}}=this,{scrollHeight:l,scrollWidth:i,scrollLeft:n,scrollTop:r,clientHeight:s,clientWidth:c}=e;o&&o({clientHeight:s,clientWidth:c,scrollHeight:l,scrollWidth:i,scrollLeft:n,scrollTop:r}),this._checkOffsetAndLoadMore()};this.state.rowCount=this.props.rowCount,this.state.columnCount=this.props.columnCount,this.state.scrollHeight=this._scrollingContainerRef.scrollingElement.scrollHeight,this.state.scrollWidth=this._scrollingContainerRef.scrollingElement.scrollWidth;const{initialScroll:c}=this.props;c&&this._scroll({scrollTop:c.top,scrollLeft:c.left}),this._onCleanup(),this._scrollingContainerRef.registerEventListener.addEventListener("scroll",s),this.state.cleanup.push((()=>{var t,e;return null===(e=null===(t=this._scrollingContainerRef)||void 0===t?void 0:t.registerEventListener)||void 0===e?void 0:e.removeEventListener("scroll",s)})),this._checkOffsetAndLoadMore()},this._onLoadComplete=function(t){var e;if(!(null===(e=this._scrollingContainerRef)||void 0===e?void 0:e.scrollingElement))return;const o=t===exports.ScrollAxisName.VERTICAL,{state:{rowCount:l=0,columnCount:i=0,scrollHeight:n,scrollWidth:r},props:{rowCount:s=0,columnCount:c=0,reverse:h={}},_scrollingContainerRef:a}=this,{scrollTop:u,scrollLeft:d,scrollHeight:p,scrollWidth:f,clientHeight:g,clientWidth:v}=a.scrollingElement,m=o?s:c,C=o?u:d,_=o?p:f,E=o?n:r,L=o?g:v;if((o?l:i)!==m&&Math.abs(C)<L){const t=h[o?"column":"row"]?-1:1;this._scroll({["scroll"+(o?"Top":"Left")]:C+(_-E)*t})}this.state.isLoading=!1,this.state[o?"scrollHeight":"scrollWidth"]=_,this.state[o?"rowCount":"columnCount"]=m,setTimeout((()=>this._checkOffsetAndLoadMore()),100)},this._onPropsChange=function(t){this.props=t;const{state:{isLoading:e},props:{rowCount:o,columnCount:l,hasMore:i},_scrollingContainerRef:n}=this;n&&(void 0===o&&(i.down||i.up)&&console.warn(`You provided props with "hasMore: { up: ${!!i.up}, down: ${!!i.down} }" but "rowCount" is "undefined"`),void 0===l&&(i.left||i.right)&&console.warn(`You provided props with "hasMore: { left: ${!!i.left}, right: ${!!i.right} }" but "columnCount" is "undefined"`),e||this._checkOffsetAndLoadMore())},this._onCleanup=function(){const{state:{cleanup:t}}=this;t.length&&(t.forEach((t=>t())),this.state.cleanup=[])},this.setRef=this._setRef.bind(this),this.onPropsChange=this._onPropsChange.bind(this),this.onCleanup=this._onCleanup.bind(this),this.props=t,this.state={rowCount:t.rowCount,columnCount:t.columnCount,scrollHeight:0,scrollWidth:0,clientHeight:0,clientWidth:0,isLoading:!1,computedScrollThreshold:{vertical:0,horizontal:0},thresholdReached:{},cleanup:[]}}}const n=t=>{const{rowCount:e,columnCount:l,hasMore:{up:n,down:r,left:s,right:c},next:h,windowScroll:a}=t,{current:{setRef:u,onPropsChange:d,onCleanup:p}}=o.useRef(new i(t));return o.useLayoutEffect((()=>(a&&u(null),a?p:void 0)),[]),o.useEffect((()=>d(t)),[e,l,n,r,s,c,h]),{setRef:u}};exports.InfiniteScroll=i,exports.default=n,exports.useInfiniteScroll=n;
"use strict";Object.defineProperty(exports,"__esModule",{value:!0});var t,e,o=require("react");function l(t,e,o,l){return new(o||(o=Promise))((function(i,n){function r(t){try{c(l.next(t))}catch(t){n(t)}}function s(t){try{c(l.throw(t))}catch(t){n(t)}}function c(t){var e;t.done?i(t.value):(e=t.value,e instanceof o?e:new o((function(t){t(e)}))).then(r,s)}c((l=l.apply(t,e||[])).next())}))}exports.ScrollAxisName=void 0,(t=exports.ScrollAxisName||(exports.ScrollAxisName={})).VERTICAL="vertical",t.HORIZONTAL="horizontal",exports.ScrollDirection=void 0,(e=exports.ScrollDirection||(exports.ScrollDirection={})).UP="up",e.DOWN="down",e.LEFT="left",e.RIGHT="right";class i{constructor(t){this._validateScrollValue=(t,e,o)=>{const l=t<0?-1:1;return Math.abs(t)>e?null!=o?o:e*l:t},this._scroll=function({scrollTop:t,scrollLeft:e}){var o;if(!(null===(o=this._scrollingContainerRef)||void 0===o?void 0:o.scrollingElement))return;const{scrollHeight:l,scrollWidth:i}=this._scrollingContainerRef.scrollingElement;void 0!==t&&(this._scrollingContainerRef.scrollingElement.scrollTop=this._validateScrollValue(t,l)),void 0!==e&&(this._scrollingContainerRef.scrollingElement.scrollLeft=this._validateScrollValue(e,i))},this._computeThreshold=function(){const{state:{clientWidth:t,clientHeight:e},props:{scrollThreshold:o=1},_scrollingContainerRef:l}=this;if(!(null==l?void 0:l.scrollingElement)||t===l.scrollingElement.clientWidth&&e===l.scrollingElement.clientHeight)return;const{clientWidth:i,clientHeight:n,scrollHeight:r,scrollWidth:s}=l.scrollingElement;let c={vertical:0,horizontal:0};if("string"==typeof o){const t=Math.abs(parseInt(o));c={vertical:this._validateScrollValue(t,r,n),horizontal:this._validateScrollValue(t,s,i)}}else{const t=o>1?1:o<=0?.1:o;c={vertical:t*n,horizontal:t*i}}this.state.computedScrollThreshold=c,this.state.clientWidth=i,this.state.clientHeight=n},this._getPossibleDirections=function(){this._computeThreshold();const{state:{clientHeight:t,clientWidth:e,computedScrollThreshold:{vertical:o,horizontal:l}},props:{reverse:i={}},_scrollingContainerRef:n}=this,{scrollHeight:r,scrollWidth:s,scrollLeft:c,scrollTop:h}=n.scrollingElement,{column:a,row:u}=i,d=(t,e)=>Math.abs(t)<=e,p=(t,e,o,l)=>Math.abs(t)>=Math.abs(e-o-l);return{[a?exports.ScrollDirection.DOWN:exports.ScrollDirection.UP]:d(h,o),[a?exports.ScrollDirection.UP:exports.ScrollDirection.DOWN]:p(h,r,t,o),[u?exports.ScrollDirection.RIGHT:exports.ScrollDirection.LEFT]:d(c,l),[u?exports.ScrollDirection.LEFT:exports.ScrollDirection.RIGHT]:p(c,s,e,l)}},this._loadByDirection=function(t,e,o){return l(this,void 0,void 0,(function*(){const{state:{isLoading:l,thresholdReached:i},props:{next:n,hasMore:r}}=this,s=t===exports.ScrollDirection.UP?exports.ScrollAxisName.VERTICAL:exports.ScrollAxisName.HORIZONTAL;if(!l){const l=r[t]&&!i[t]&&o[t],c=!l&&r[e]&&!i[e]&&o[e];if(l||c)try{const o=l?t:e;this.state.thresholdReached[o]=!0,this.state.isLoading=!0,yield n(o)}finally{setTimeout((()=>this._onLoadComplete(s)),0)}}}))},this._checkOffsetAndLoadMore=function(){const{_scrollingContainerRef:t}=this;if(!t)return;const e=this._getPossibleDirections(),o=t=>{!e[t]&&this.state.thresholdReached[t]&&(this.state.thresholdReached[t]=!1)};Object.values(exports.ScrollDirection).forEach((t=>o(t))),this._loadByDirection(exports.ScrollDirection.UP,exports.ScrollDirection.DOWN,e),this._loadByDirection(exports.ScrollDirection.LEFT,exports.ScrollDirection.RIGHT,e)},this._setRef=function(t){var e,o,l;const i={scrollingElement:null,registerEventListener:null};if(this.props.windowScroll)i.scrollingElement=document.scrollingElement,i.registerEventListener=document;else{const n=null!==(l=null!==(e=null==t?void 0:t._scrollingContainer)&&void 0!==e?e:null===(o=null==t?void 0:t.Grid)||void 0===o?void 0:o._scrollingContainer)&&void 0!==l?l:t;i.scrollingElement=n,i.registerEventListener=n}const{scrollingElement:n,registerEventListener:r}=i;if(n&&r&&("number"!=typeof n.scrollHeight||"number"!=typeof n.scrollWidth||"number"!=typeof n.scrollLeft||"number"!=typeof n.scrollTop||"number"!=typeof n.clientHeight||"number"!=typeof n.clientWidth||"function"!=typeof r.addEventListener||"function"!=typeof r.removeEventListener)||!n||!r)return void console.error("Sorry I can't use this container - try using a different DOM element.");this._scrollingContainerRef=i;const s=()=>{var t;if(!(null===(t=this._scrollingContainerRef)||void 0===t?void 0:t.scrollingElement))return;const{_scrollingContainerRef:{scrollingElement:e},props:{onScroll:o}}=this,{scrollHeight:l,scrollWidth:i,scrollLeft:n,scrollTop:r,clientHeight:s,clientWidth:c}=e;o&&o({clientHeight:s,clientWidth:c,scrollHeight:l,scrollWidth:i,scrollLeft:n,scrollTop:r}),this._checkOffsetAndLoadMore()};this.state.rowCount=this.props.rowCount,this.state.columnCount=this.props.columnCount,this.state.scrollHeight=this._scrollingContainerRef.scrollingElement.scrollHeight,this.state.scrollWidth=this._scrollingContainerRef.scrollingElement.scrollWidth;const{initialScroll:c}=this.props;c&&this._scroll({scrollTop:c.top,scrollLeft:c.left}),this._onCleanup(),this._scrollingContainerRef.registerEventListener.addEventListener("scroll",s),this.state.cleanup.push((()=>{var t,e;return null===(e=null===(t=this._scrollingContainerRef)||void 0===t?void 0:t.registerEventListener)||void 0===e?void 0:e.removeEventListener("scroll",s)})),this._checkOffsetAndLoadMore()},this._onLoadComplete=function(t){var e;if(!(null===(e=this._scrollingContainerRef)||void 0===e?void 0:e.scrollingElement))return;const o=t===exports.ScrollAxisName.VERTICAL,{state:{rowCount:l=0,columnCount:i=0,scrollHeight:n,scrollWidth:r},props:{rowCount:s=0,columnCount:c=0,reverse:h={}},_scrollingContainerRef:a}=this,{scrollTop:u,scrollLeft:d,scrollHeight:p,scrollWidth:f,clientHeight:g,clientWidth:v}=a.scrollingElement,m=o?s:c,C=o?u:d,_=o?p:f,E=o?n:r,L=o?g:v;if((o?l:i)!==m&&Math.abs(C)<L){const t=h[o?"column":"row"]?-1:1;this._scroll({["scroll"+(o?"Top":"Left")]:C+(_-E)*t})}this.state.isLoading=!1,this.state[o?"scrollHeight":"scrollWidth"]=_,this.state[o?"rowCount":"columnCount"]=m,setTimeout((()=>this._checkOffsetAndLoadMore()),100)},this._onPropsChange=function(t){this.props=t;const{state:{isLoading:e},props:{rowCount:o,columnCount:l,hasMore:i},_scrollingContainerRef:n}=this;n&&(void 0===o&&(i.down||i.up)&&console.warn(`You provided props with "hasMore: { up: ${!!i.up}, down: ${!!i.down} }" but "rowCount" is "undefined"`),void 0===l&&(i.left||i.right)&&console.warn(`You provided props with "hasMore: { left: ${!!i.left}, right: ${!!i.right} }" but "columnCount" is "undefined"`),e||this._checkOffsetAndLoadMore())},this._onCleanup=function(){const{state:{cleanup:t}}=this;t.length&&(t.forEach((t=>t())),this.state.cleanup=[])},this.setRef=this._setRef.bind(this),this.onPropsChange=this._onPropsChange.bind(this),this.onCleanup=this._onCleanup.bind(this),this.props=t,this.state={rowCount:t.rowCount,columnCount:t.columnCount,scrollHeight:0,scrollWidth:0,clientHeight:0,clientWidth:0,isLoading:!1,computedScrollThreshold:{vertical:0,horizontal:0},thresholdReached:{},cleanup:[]}}}const n=t=>{const e=o.useRef(null),{rowCount:l,columnCount:n,hasMore:{up:r,down:s,left:c,right:h},next:a,windowScroll:u}=t,{current:{setRef:d,onPropsChange:p,onCleanup:f}}=o.useRef(new i(t));return o.useEffect((()=>(d(u?null:e.current),f)),[e.current]),o.useEffect((()=>p(t)),[l,n,r,s,c,h,a]),e};exports.InfiniteScroll=i,exports.default=n,exports.useInfiniteScroll=n;
//# sourceMappingURL=index.js.map

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

/// <reference types="react" />
export interface ClientSize {

@@ -65,5 +66,3 @@ clientHeight?: number;

};
export interface UseInfiniteScrollResult {
setRef: SetRefFn;
}
export declare type InfiniteScrollRef<T> = React.MutableRefObject<T | null>;
export declare type InfiniteScrollProps = UseInfiniteScrollProps;

@@ -70,0 +69,0 @@ export declare type ScrollOffsetValues = Required<ScrollDirectionState>;

@@ -1,3 +0,3 @@

import { UseInfiniteScrollResult, UseInfiniteScrollProps } from './types';
declare const useInfiniteScroll: (props: UseInfiniteScrollProps) => UseInfiniteScrollResult;
import { InfiniteScrollRef, UseInfiniteScrollProps } from './types';
declare const useInfiniteScroll: <T = any>(props: UseInfiniteScrollProps) => InfiniteScrollRef<T>;
export default useInfiniteScroll;

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

import{useRef as t,useLayoutEffect as e,useEffect as o}from"react";function n(t,e,o,n){return new(o||(o=Promise))((function(l,i){function s(t){try{c(n.next(t))}catch(t){i(t)}}function r(t){try{c(n.throw(t))}catch(t){i(t)}}function c(t){var e;t.done?l(t.value):(e=t.value,e instanceof o?e:new o((function(t){t(e)}))).then(s,r)}c((n=n.apply(t,e||[])).next())}))}var l,i;!function(t){t.VERTICAL="vertical",t.HORIZONTAL="horizontal"}(l||(l={})),function(t){t.UP="up",t.DOWN="down",t.LEFT="left",t.RIGHT="right"}(i||(i={}));class s{constructor(t){this._validateScrollValue=(t,e,o)=>{const n=t<0?-1:1;return Math.abs(t)>e?null!=o?o:e*n:t},this._scroll=function({scrollTop:t,scrollLeft:e}){var o;if(!(null===(o=this._scrollingContainerRef)||void 0===o?void 0:o.scrollingElement))return;const{scrollHeight:n,scrollWidth:l}=this._scrollingContainerRef.scrollingElement;void 0!==t&&(this._scrollingContainerRef.scrollingElement.scrollTop=this._validateScrollValue(t,n)),void 0!==e&&(this._scrollingContainerRef.scrollingElement.scrollLeft=this._validateScrollValue(e,l))},this._computeThreshold=function(){const{state:{clientWidth:t,clientHeight:e},props:{scrollThreshold:o=1},_scrollingContainerRef:n}=this;if(!(null==n?void 0:n.scrollingElement)||t===n.scrollingElement.clientWidth&&e===n.scrollingElement.clientHeight)return;const{clientWidth:l,clientHeight:i,scrollHeight:s,scrollWidth:r}=n.scrollingElement;let c={vertical:0,horizontal:0};if("string"==typeof o){const t=Math.abs(parseInt(o));c={vertical:this._validateScrollValue(t,s,i),horizontal:this._validateScrollValue(t,r,l)}}else{const t=o>1?1:o<=0?.1:o;c={vertical:t*i,horizontal:t*l}}this.state.computedScrollThreshold=c,this.state.clientWidth=l,this.state.clientHeight=i},this._getPossibleDirections=function(){this._computeThreshold();const{state:{clientHeight:t,clientWidth:e,computedScrollThreshold:{vertical:o,horizontal:n}},props:{reverse:l={}},_scrollingContainerRef:s}=this,{scrollHeight:r,scrollWidth:c,scrollLeft:h,scrollTop:a}=s.scrollingElement,{column:u,row:d}=l,f=(t,e)=>Math.abs(t)<=e,g=(t,e,o,n)=>Math.abs(t)>=Math.abs(e-o-n);return{[u?i.DOWN:i.UP]:f(a,o),[u?i.UP:i.DOWN]:g(a,r,t,o),[d?i.RIGHT:i.LEFT]:f(h,n),[d?i.LEFT:i.RIGHT]:g(h,c,e,n)}},this._loadByDirection=function(t,e,o){return n(this,void 0,void 0,(function*(){const{state:{isLoading:n,thresholdReached:s},props:{next:r,hasMore:c}}=this,h=t===i.UP?l.VERTICAL:l.HORIZONTAL;if(!n){const n=c[t]&&!s[t]&&o[t],l=!n&&c[e]&&!s[e]&&o[e];if(n||l)try{const o=n?t:e;this.state.thresholdReached[o]=!0,this.state.isLoading=!0,yield r(o)}finally{setTimeout((()=>this._onLoadComplete(h)),0)}}}))},this._checkOffsetAndLoadMore=function(){const{_scrollingContainerRef:t}=this;if(!t)return;const e=this._getPossibleDirections(),o=t=>{!e[t]&&this.state.thresholdReached[t]&&(this.state.thresholdReached[t]=!1)};Object.values(i).forEach((t=>o(t))),this._loadByDirection(i.UP,i.DOWN,e),this._loadByDirection(i.LEFT,i.RIGHT,e)},this._setRef=function(t){var e,o,n;const l={scrollingElement:null,registerEventListener:null};if(this.props.windowScroll)l.scrollingElement=document.scrollingElement,l.registerEventListener=document;else{const i=null!==(n=null!==(e=null==t?void 0:t._scrollingContainer)&&void 0!==e?e:null===(o=null==t?void 0:t.Grid)||void 0===o?void 0:o._scrollingContainer)&&void 0!==n?n:t;l.scrollingElement=i,l.registerEventListener=i}const{scrollingElement:i,registerEventListener:s}=l;if(i&&s&&("number"!=typeof i.scrollHeight||"number"!=typeof i.scrollWidth||"number"!=typeof i.scrollLeft||"number"!=typeof i.scrollTop||"number"!=typeof i.clientHeight||"number"!=typeof i.clientWidth||"function"!=typeof s.addEventListener||"function"!=typeof s.removeEventListener)||!i||!s)return void console.error("Sorry I can't use this container - try using a different DOM element.");this._scrollingContainerRef=l;const r=()=>{var t;if(!(null===(t=this._scrollingContainerRef)||void 0===t?void 0:t.scrollingElement))return;const{_scrollingContainerRef:{scrollingElement:e},props:{onScroll:o}}=this,{scrollHeight:n,scrollWidth:l,scrollLeft:i,scrollTop:s,clientHeight:r,clientWidth:c}=e;o&&o({clientHeight:r,clientWidth:c,scrollHeight:n,scrollWidth:l,scrollLeft:i,scrollTop:s}),this._checkOffsetAndLoadMore()};this.state.rowCount=this.props.rowCount,this.state.columnCount=this.props.columnCount,this.state.scrollHeight=this._scrollingContainerRef.scrollingElement.scrollHeight,this.state.scrollWidth=this._scrollingContainerRef.scrollingElement.scrollWidth;const{initialScroll:c}=this.props;c&&this._scroll({scrollTop:c.top,scrollLeft:c.left}),this._onCleanup(),this._scrollingContainerRef.registerEventListener.addEventListener("scroll",r),this.state.cleanup.push((()=>{var t,e;return null===(e=null===(t=this._scrollingContainerRef)||void 0===t?void 0:t.registerEventListener)||void 0===e?void 0:e.removeEventListener("scroll",r)})),this._checkOffsetAndLoadMore()},this._onLoadComplete=function(t){var e;if(!(null===(e=this._scrollingContainerRef)||void 0===e?void 0:e.scrollingElement))return;const o=t===l.VERTICAL,{state:{rowCount:n=0,columnCount:i=0,scrollHeight:s,scrollWidth:r},props:{rowCount:c=0,columnCount:h=0,reverse:a={}},_scrollingContainerRef:u}=this,{scrollTop:d,scrollLeft:f,scrollHeight:g,scrollWidth:p,clientHeight:v,clientWidth:m}=u.scrollingElement,C=o?c:h,_=o?d:f,L=o?g:p,E=o?s:r,R=o?v:m;if((o?n:i)!==C&&Math.abs(_)<R){const t=a[o?"column":"row"]?-1:1;this._scroll({["scroll"+(o?"Top":"Left")]:_+(L-E)*t})}this.state.isLoading=!1,this.state[o?"scrollHeight":"scrollWidth"]=L,this.state[o?"rowCount":"columnCount"]=C,setTimeout((()=>this._checkOffsetAndLoadMore()),100)},this._onPropsChange=function(t){this.props=t;const{state:{isLoading:e},props:{rowCount:o,columnCount:n,hasMore:l},_scrollingContainerRef:i}=this;i&&(void 0===o&&(l.down||l.up)&&console.warn(`You provided props with "hasMore: { up: ${!!l.up}, down: ${!!l.down} }" but "rowCount" is "undefined"`),void 0===n&&(l.left||l.right)&&console.warn(`You provided props with "hasMore: { left: ${!!l.left}, right: ${!!l.right} }" but "columnCount" is "undefined"`),e||this._checkOffsetAndLoadMore())},this._onCleanup=function(){const{state:{cleanup:t}}=this;t.length&&(t.forEach((t=>t())),this.state.cleanup=[])},this.setRef=this._setRef.bind(this),this.onPropsChange=this._onPropsChange.bind(this),this.onCleanup=this._onCleanup.bind(this),this.props=t,this.state={rowCount:t.rowCount,columnCount:t.columnCount,scrollHeight:0,scrollWidth:0,clientHeight:0,clientWidth:0,isLoading:!1,computedScrollThreshold:{vertical:0,horizontal:0},thresholdReached:{},cleanup:[]}}}const r=n=>{const{rowCount:l,columnCount:i,hasMore:{up:r,down:c,left:h,right:a},next:u,windowScroll:d}=n,{current:{setRef:f,onPropsChange:g,onCleanup:p}}=t(new s(n));return e((()=>(d&&f(null),d?p:void 0)),[]),o((()=>g(n)),[l,i,r,c,h,a,u]),{setRef:f}};export{s as InfiniteScroll,l as ScrollAxisName,i as ScrollDirection,r as default,r as useInfiniteScroll};
import{useRef as t,useEffect as e}from"react";function o(t,e,o,n){return new(o||(o=Promise))((function(l,i){function s(t){try{c(n.next(t))}catch(t){i(t)}}function r(t){try{c(n.throw(t))}catch(t){i(t)}}function c(t){var e;t.done?l(t.value):(e=t.value,e instanceof o?e:new o((function(t){t(e)}))).then(s,r)}c((n=n.apply(t,e||[])).next())}))}var n,l;!function(t){t.VERTICAL="vertical",t.HORIZONTAL="horizontal"}(n||(n={})),function(t){t.UP="up",t.DOWN="down",t.LEFT="left",t.RIGHT="right"}(l||(l={}));class i{constructor(t){this._validateScrollValue=(t,e,o)=>{const n=t<0?-1:1;return Math.abs(t)>e?null!=o?o:e*n:t},this._scroll=function({scrollTop:t,scrollLeft:e}){var o;if(!(null===(o=this._scrollingContainerRef)||void 0===o?void 0:o.scrollingElement))return;const{scrollHeight:n,scrollWidth:l}=this._scrollingContainerRef.scrollingElement;void 0!==t&&(this._scrollingContainerRef.scrollingElement.scrollTop=this._validateScrollValue(t,n)),void 0!==e&&(this._scrollingContainerRef.scrollingElement.scrollLeft=this._validateScrollValue(e,l))},this._computeThreshold=function(){const{state:{clientWidth:t,clientHeight:e},props:{scrollThreshold:o=1},_scrollingContainerRef:n}=this;if(!(null==n?void 0:n.scrollingElement)||t===n.scrollingElement.clientWidth&&e===n.scrollingElement.clientHeight)return;const{clientWidth:l,clientHeight:i,scrollHeight:s,scrollWidth:r}=n.scrollingElement;let c={vertical:0,horizontal:0};if("string"==typeof o){const t=Math.abs(parseInt(o));c={vertical:this._validateScrollValue(t,s,i),horizontal:this._validateScrollValue(t,r,l)}}else{const t=o>1?1:o<=0?.1:o;c={vertical:t*i,horizontal:t*l}}this.state.computedScrollThreshold=c,this.state.clientWidth=l,this.state.clientHeight=i},this._getPossibleDirections=function(){this._computeThreshold();const{state:{clientHeight:t,clientWidth:e,computedScrollThreshold:{vertical:o,horizontal:n}},props:{reverse:i={}},_scrollingContainerRef:s}=this,{scrollHeight:r,scrollWidth:c,scrollLeft:h,scrollTop:a}=s.scrollingElement,{column:u,row:d}=i,f=(t,e)=>Math.abs(t)<=e,g=(t,e,o,n)=>Math.abs(t)>=Math.abs(e-o-n);return{[u?l.DOWN:l.UP]:f(a,o),[u?l.UP:l.DOWN]:g(a,r,t,o),[d?l.RIGHT:l.LEFT]:f(h,n),[d?l.LEFT:l.RIGHT]:g(h,c,e,n)}},this._loadByDirection=function(t,e,i){return o(this,void 0,void 0,(function*(){const{state:{isLoading:o,thresholdReached:s},props:{next:r,hasMore:c}}=this,h=t===l.UP?n.VERTICAL:n.HORIZONTAL;if(!o){const o=c[t]&&!s[t]&&i[t],n=!o&&c[e]&&!s[e]&&i[e];if(o||n)try{const n=o?t:e;this.state.thresholdReached[n]=!0,this.state.isLoading=!0,yield r(n)}finally{setTimeout((()=>this._onLoadComplete(h)),0)}}}))},this._checkOffsetAndLoadMore=function(){const{_scrollingContainerRef:t}=this;if(!t)return;const e=this._getPossibleDirections(),o=t=>{!e[t]&&this.state.thresholdReached[t]&&(this.state.thresholdReached[t]=!1)};Object.values(l).forEach((t=>o(t))),this._loadByDirection(l.UP,l.DOWN,e),this._loadByDirection(l.LEFT,l.RIGHT,e)},this._setRef=function(t){var e,o,n;const l={scrollingElement:null,registerEventListener:null};if(this.props.windowScroll)l.scrollingElement=document.scrollingElement,l.registerEventListener=document;else{const i=null!==(n=null!==(e=null==t?void 0:t._scrollingContainer)&&void 0!==e?e:null===(o=null==t?void 0:t.Grid)||void 0===o?void 0:o._scrollingContainer)&&void 0!==n?n:t;l.scrollingElement=i,l.registerEventListener=i}const{scrollingElement:i,registerEventListener:s}=l;if(i&&s&&("number"!=typeof i.scrollHeight||"number"!=typeof i.scrollWidth||"number"!=typeof i.scrollLeft||"number"!=typeof i.scrollTop||"number"!=typeof i.clientHeight||"number"!=typeof i.clientWidth||"function"!=typeof s.addEventListener||"function"!=typeof s.removeEventListener)||!i||!s)return void console.error("Sorry I can't use this container - try using a different DOM element.");this._scrollingContainerRef=l;const r=()=>{var t;if(!(null===(t=this._scrollingContainerRef)||void 0===t?void 0:t.scrollingElement))return;const{_scrollingContainerRef:{scrollingElement:e},props:{onScroll:o}}=this,{scrollHeight:n,scrollWidth:l,scrollLeft:i,scrollTop:s,clientHeight:r,clientWidth:c}=e;o&&o({clientHeight:r,clientWidth:c,scrollHeight:n,scrollWidth:l,scrollLeft:i,scrollTop:s}),this._checkOffsetAndLoadMore()};this.state.rowCount=this.props.rowCount,this.state.columnCount=this.props.columnCount,this.state.scrollHeight=this._scrollingContainerRef.scrollingElement.scrollHeight,this.state.scrollWidth=this._scrollingContainerRef.scrollingElement.scrollWidth;const{initialScroll:c}=this.props;c&&this._scroll({scrollTop:c.top,scrollLeft:c.left}),this._onCleanup(),this._scrollingContainerRef.registerEventListener.addEventListener("scroll",r),this.state.cleanup.push((()=>{var t,e;return null===(e=null===(t=this._scrollingContainerRef)||void 0===t?void 0:t.registerEventListener)||void 0===e?void 0:e.removeEventListener("scroll",r)})),this._checkOffsetAndLoadMore()},this._onLoadComplete=function(t){var e;if(!(null===(e=this._scrollingContainerRef)||void 0===e?void 0:e.scrollingElement))return;const o=t===n.VERTICAL,{state:{rowCount:l=0,columnCount:i=0,scrollHeight:s,scrollWidth:r},props:{rowCount:c=0,columnCount:h=0,reverse:a={}},_scrollingContainerRef:u}=this,{scrollTop:d,scrollLeft:f,scrollHeight:g,scrollWidth:p,clientHeight:v,clientWidth:m}=u.scrollingElement,C=o?c:h,_=o?d:f,L=o?g:p,E=o?s:r,R=o?v:m;if((o?l:i)!==C&&Math.abs(_)<R){const t=a[o?"column":"row"]?-1:1;this._scroll({["scroll"+(o?"Top":"Left")]:_+(L-E)*t})}this.state.isLoading=!1,this.state[o?"scrollHeight":"scrollWidth"]=L,this.state[o?"rowCount":"columnCount"]=C,setTimeout((()=>this._checkOffsetAndLoadMore()),100)},this._onPropsChange=function(t){this.props=t;const{state:{isLoading:e},props:{rowCount:o,columnCount:n,hasMore:l},_scrollingContainerRef:i}=this;i&&(void 0===o&&(l.down||l.up)&&console.warn(`You provided props with "hasMore: { up: ${!!l.up}, down: ${!!l.down} }" but "rowCount" is "undefined"`),void 0===n&&(l.left||l.right)&&console.warn(`You provided props with "hasMore: { left: ${!!l.left}, right: ${!!l.right} }" but "columnCount" is "undefined"`),e||this._checkOffsetAndLoadMore())},this._onCleanup=function(){const{state:{cleanup:t}}=this;t.length&&(t.forEach((t=>t())),this.state.cleanup=[])},this.setRef=this._setRef.bind(this),this.onPropsChange=this._onPropsChange.bind(this),this.onCleanup=this._onCleanup.bind(this),this.props=t,this.state={rowCount:t.rowCount,columnCount:t.columnCount,scrollHeight:0,scrollWidth:0,clientHeight:0,clientWidth:0,isLoading:!1,computedScrollThreshold:{vertical:0,horizontal:0},thresholdReached:{},cleanup:[]}}}const s=o=>{const n=t(null),{rowCount:l,columnCount:s,hasMore:{up:r,down:c,left:h,right:a},next:u,windowScroll:d}=o,{current:{setRef:f,onPropsChange:g,onCleanup:p}}=t(new i(o));return e((()=>(f(d?null:n.current),p)),[n.current]),e((()=>g(o)),[l,s,r,c,h,a,u]),n};export{i as InfiniteScroll,n as ScrollAxisName,l as ScrollDirection,s as default,s as useInfiniteScroll};
//# sourceMappingURL=index.js.map

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

/// <reference types="react" />
export interface ClientSize {

@@ -65,5 +66,3 @@ clientHeight?: number;

};
export interface UseInfiniteScrollResult {
setRef: SetRefFn;
}
export declare type InfiniteScrollRef<T> = React.MutableRefObject<T | null>;
export declare type InfiniteScrollProps = UseInfiniteScrollProps;

@@ -70,0 +69,0 @@ export declare type ScrollOffsetValues = Required<ScrollDirectionState>;

@@ -1,3 +0,3 @@

import { UseInfiniteScrollResult, UseInfiniteScrollProps } from './types';
declare const useInfiniteScroll: (props: UseInfiniteScrollProps) => UseInfiniteScrollResult;
import { InfiniteScrollRef, UseInfiniteScrollProps } from './types';
declare const useInfiniteScroll: <T = any>(props: UseInfiniteScrollProps) => InfiniteScrollRef<T>;
export default useInfiniteScroll;

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

/// <reference types="react" />
interface ClientSize {

@@ -65,9 +66,7 @@ clientHeight?: number;

};
interface UseInfiniteScrollResult {
setRef: SetRefFn;
}
declare type InfiniteScrollRef<T> = React.MutableRefObject<T | null>;
declare type InfiniteScrollProps = UseInfiniteScrollProps;
declare type ScrollOffsetValues = Required<ScrollDirectionState>;
declare const useInfiniteScroll: (props: UseInfiniteScrollProps) => UseInfiniteScrollResult;
declare const useInfiniteScroll: <T = any>(props: UseInfiniteScrollProps) => InfiniteScrollRef<T>;

@@ -94,2 +93,2 @@ declare class InfiniteScroll {

export { ClientSize, DatasetLength, EventListenerFn, InfiniteScroll, InfiniteScrollProps, InfiniteScrollState, RegisterEventListener, ScrollAxis, ScrollAxisName, ScrollDirection, ScrollDirectionState, ScrollOffsetValues, ScrollParams, ScrollPosition, ScrollSize, ScrollingContainerRef, ScrollingElementRef, SetRefFn, UseInfiniteScrollProps, UseInfiniteScrollResult, useInfiniteScroll as default, useInfiniteScroll };
export { ClientSize, DatasetLength, EventListenerFn, InfiniteScroll, InfiniteScrollProps, InfiniteScrollRef, InfiniteScrollState, RegisterEventListener, ScrollAxis, ScrollAxisName, ScrollDirection, ScrollDirectionState, ScrollOffsetValues, ScrollParams, ScrollPosition, ScrollSize, ScrollingContainerRef, ScrollingElementRef, SetRefFn, UseInfiniteScrollProps, useInfiniteScroll as default, useInfiniteScroll };
{
"name": "react-easy-infinite-scroll-hook",
"version": "1.8.7",
"version": "1.9.0",
"license": "MIT",

@@ -16,2 +16,3 @@ "description": "A react hook for creating simple, fast and lightweight components with infinite scrolling in any direction, supporting both windowed and scrollable elements.",

"build": "rimraf dist && rollup -c",
"prepublish": "yarn build",
"lint": "eslint 'src/**/*.{ts,tsx,js,jsx}'",

@@ -18,0 +19,0 @@ "lint:fix": "yarn lint --fix",

@@ -45,5 +45,5 @@ # react-easy-infinite-scroll-hook

| Name | Description | Link |
| :--: | -- | :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: |
| Simple List | Simple list component with infinite scroll `down` | [![Edit useInfiniteScroll](https://codesandbox.io/static/img/play-codesandbox.svg)](https://codesandbox.io/s/react-easy-infinite-scroll-hook-6w9szb) |
| Name | Description | Link |
| :---------: | ------------------------------------------------------------------- | :----------------------------------------------------------------------------------------------------------------------------------------------------------------: |
| Simple List | Simple list component with infinite scroll `down` | [![Edit useInfiniteScroll](https://codesandbox.io/static/img/play-codesandbox.svg)](https://codesandbox.io/s/react-easy-infinite-scroll-hook-6w9szb) |
| Window List | Infinite scroll list that uses the window's scroll as its container | [![Edit useInfiniteScroll](https://codesandbox.io/static/img/play-codesandbox.svg)](https://codesandbox.io/s/react-easy-infinite-scroll-hook-window-scroll-863k1m) |

@@ -57,3 +57,5 @@

const InfiniteListComponent = ({ isLoading, items, canLoadMore, next }) => {
const { setRef } = useInfiniteScroll({
// FYI TypeScript usage:
// const ref = useInfiniteScroll<YourElemntType>(...props);
const ref = useInfiniteScroll({
// Function to fetch more items

@@ -73,3 +75,3 @@ next,

<div
ref={setRef}
ref={ref}
style={{

@@ -95,6 +97,6 @@ height: 500,

| Component | Description | Link |
| :--: | -- | :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: |
| List | Virtualized `List` component with infinite scroll | [![Edit useInfiniteScroll](https://codesandbox.io/static/img/play-codesandbox.svg)](https://codesandbox.io/s/react-easy-infinite-scroll-hook-virtualized-mdfpyu) |
| Grid | Virtualized `Grid` component with infinite scroll `down` and `right` | [![Edit useInfiniteScroll](https://codesandbox.io/static/img/play-codesandbox.svg)](https://codesandbox.io/s/react-easy-infinite-scroll-hook-virtualized-grid-rlmfd9?file=/src/App.tsx) |
| Component | Description | Link |
| :-------: | -------------------------------------------------------------------- | :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: |
| List | Virtualized `List` component with infinite scroll | [![Edit useInfiniteScroll](https://codesandbox.io/static/img/play-codesandbox.svg)](https://codesandbox.io/s/react-easy-infinite-scroll-hook-virtualized-mdfpyu) |
| Grid | Virtualized `Grid` component with infinite scroll `down` and `right` | [![Edit useInfiniteScroll](https://codesandbox.io/static/img/play-codesandbox.svg)](https://codesandbox.io/s/react-easy-infinite-scroll-hook-virtualized-grid-rlmfd9?file=/src/App.tsx) |

@@ -108,3 +110,3 @@ <br />

const VirtualizedInfiniteListComponent = ({ isLoading, items, canLoadMore, next }) => {
const { setRef } = useInfiniteScroll({
const ref = useInfiniteScroll({
next,

@@ -118,3 +120,3 @@ rowCount: items.length,

<List
ref={setRef}
ref={ref}
width={500}

@@ -142,17 +144,17 @@ height={500}

After initialization, this hook returns a `setRef` function, which you must pass to your element `ref`.
After initialization, this hook returns a React `ref` object, which you must pass to your element `ref`.
### Props
| Name | Required | Description | Type | Default Value |
| --------------- | --------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------- | :-----------: |
| next | Yes | A callback when more items are requested by the user. Receives a single parameter specifying the direction to load e.g. `(direction) => Promise<void>` | Function | |
| hasMore | Yes | Whether there are more items to load. If marked `true` in the specified direction, it will try to load more items if the threshold is reached. Expect object with directions to load `{ up: false, down: false, left: false, right: false }` | object | |
| rowCount | Condition | Number of items in a `vertical` list (scroll axis `Y`). Required if you are using `vertical` scroll. | number | |
| columnCount | Condition | Number of items in a `horizontal` list (scroll axis `X`). Required if you are using `horizontal` scroll. | number | |
| onScroll | | The callback is called when the container is scrolled: `({ clientHeight: number, scrollHeight: number, scrollTop: number, clientWidth: number, scrollWidth: number, scrollLeft: number }) => void` | Function | |
| initialScroll | | The initial scroll position of the element, which is applied after the ref has been initialized | object | |
| reverse | | The direction of the scroll axis is used to create scrolling in the opposite direction, for example when using the CSS style `flex-direction: 'row-reverse'` | object | |
| scrollThreshold | | The threshold at which the next function is called. It can be specified in pixels from the scrollbar value, for example `'200px'` and as a percentage of the container size `from 0.1 to 1` (`1` is `100%`) | number or string | `1` |
| windowScroll | | When set to `true`, uses a window as the scroll element. If you are using a scroll window, then anything you pass to the `setRef` function will be ignored | boolean | `false` |
| Name | Required | Description | Type | Default Value |
| --------------- | --------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------- | :-----------: |
| next | Yes | A callback when more items are requested by the user. Receives a single parameter specifying the direction to load e.g. `(direction) => Promise<void>` | Function | |
| hasMore | Yes | Whether there are more items to load. If marked `true` in the specified direction, it will try to load more items if the threshold is reached. Expect object with directions to load `{ up: false, down: false, left: false, right: false }` | object | |
| rowCount | Condition | Number of items in a `vertical` list (scroll axis `Y`). Required if you are using `vertical` scroll. | number | |
| columnCount | Condition | Number of items in a `horizontal` list (scroll axis `X`). Required if you are using `horizontal` scroll. | number | |
| onScroll | | The callback is called when the container is scrolled: `({ clientHeight: number, scrollHeight: number, scrollTop: number, clientWidth: number, scrollWidth: number, scrollLeft: number }) => void` | Function | |
| initialScroll | | The initial scroll position of the element, which is applied after the ref has been initialized | object | |
| reverse | | The direction of the scroll axis is used to create scrolling in the opposite direction, for example when using the CSS style `flex-direction: 'row-reverse'` | object | |
| scrollThreshold | | The threshold at which the next function is called. It can be specified in pixels from the scrollbar value, for example `'200px'` and as a percentage of the container size `from 0.1 to 1` (`1` is `100%`) | number or string | `1` |
| windowScroll | | When set to `true`, uses a window as the scroll element. If you are using a scroll window, then anything you pass to the `ref` will be ignored | boolean | `false` |

@@ -168,3 +170,3 @@ ## Friends

> Yes you can! To use it with other libraries you must specify the correct DOM element for the `setRef` function.
> Yes you can! To use it with other libraries you must specify the correct DOM element for the `ref` object.

@@ -177,3 +179,3 @@ ### Can I use it with `flex-direction: 'column-reverse'`?

> `MultiGrid` is a complex component with a lot of scrollable containers, and to use it you must specify the correct container for the `setRef` function:
> `MultiGrid` is a complex component with a lot of scrollable containers, and to use it you must specify the correct container for the `ref` object:

@@ -186,3 +188,3 @@ ```js

const VirtualizedInfiniteMultiGridComponent = ({ isLoading, items, canLoadMore, next }) => {
const { setRef } = useInfiniteScroll({
const ref = useInfiniteScroll({
next,

@@ -196,5 +198,5 @@ columnCount: items.length,

(node) => {
setRef(node._bottomRightGrid);
ref.current = node._bottomRightGrid;
},
[setRef]
[ref]
);

@@ -201,0 +203,0 @@

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