react-scrollsense
Version:
A lightweight scroll sensor to solve your react scroll into viewport issues.
3 lines (2 loc) • 11.9 kB
JavaScript
"use strict";Object.defineProperty(exports,"__esModule",{value:!0});var t=require("react/jsx-runtime"),o=require("react"),e=require("prop-types"),r=require("../pack.b563688a.js");function n(t){return t&&"object"==typeof t&&"default"in t?t:{default:t}}var i=n(o),s=n(e);function l(t){return!isNaN(parseFloat(t))&&isFinite(t)}const h=i.default.createContext(null);h.displayName="ScrollSenseIO";const a=function(t){if(null==t||void 0===t)return.5;let o=null;return o=t instanceof Array?t:[t],o.map((t=>{let o=t.toString(),e=-1;if((e=o.indexOf("%"))>-1){let t=o.substr(0,e);return t=parseFloat(t),t/=100,t}return(e=o.indexOf("px"))>-1?(r.error(r.errorStrings.noPixelsForSingleIOThreshold),.5):t}))};class c extends i.default.Component{constructor(t){super(t),this.callbackfns={},this.io=null,this.perComponentIOArray=[],this.i=0,this.addTrackingFn=this.addTrackingFn.bind(this),this.addPerComponentFn=this.addPerComponentFn.bind(this),this.replaceComponentFn=this.replaceComponentFn.bind(this),this.wrappedPerComponentHandler=this.wrappedPerComponentHandler.bind(this),this.removeTrackingFn=this.removeTrackingFn.bind(this)}onContentVisible(t,o){t.forEach((t=>{let o=t.target;const e=this.callbackfns[o.getAttribute("data-scroll-id")].fn;e&&e(t)}))}onViewportChange(){this.setState({refreshToggle:!this.state.refreshToggle})}componentWillUnmount(){for(let t in this.callbackfns)this.io.unobserve(this.callbackfns[t].el);this.io&&this.io.disconnect();for(let t=0;t<this.perComponentIOArray.length;t++){const o=this.perComponentIOArray[t];o.io.unobserve(o.el),o.io.disconnect()}}replaceComponentFn(t,o,e){for(let n=0;n<this.perComponentIOArray.length;n++){const i=this.perComponentIOArray[n];if(i.el==t){let n=i.io;n.unobserve(t),n.disconnect();var r=this.buildOptions(t,e);return n=new IntersectionObserver(this.wrappedPerComponentHandler,r),i.io=n,i.fn=o,n.observe(t),i.ioActions.pause=()=>{this.pauseTrackingFn(t,n)},i.ioActions.resume=()=>{this.resumeTrackingFn(t,n)},i.ioActions}}}buildOptions(t,o){var e,r,n,i,s;let l=o;return l=l?{threshold:null!==(r=l.threshold)&&void 0!==r?r:this.props.config&&this.props.config.threshold||.5,root:null!==(n=l.root)&&void 0!==n?n:null===(i=this.props.config)||void 0===i?void 0:i.root,rootMargin:null!==(s=l.rootMargin)&&void 0!==s?s:this.props.config&&this.props.config.rootMargin||"0px"}:{threshold:this.props.config&&this.props.config.threshold||.5,root:null===(e=this.props.config)||void 0===e?void 0:e.root,rootMargin:this.props.config&&this.props.config.rootMargin||"0px"},l.threshold=function(t,o){let e=null;return e=t instanceof Array?t:[t],e.map((t=>{let e=t.toString(),r=-1;if((r=e.indexOf("%"))>-1){let t=e.substr(0,r);return t=parseInt(t),t/=100,t}if((r=e.indexOf("px"))>-1){let t=e.substr(0,r);t=parseInt(t);let n=o.getBoundingClientRect();return t=Math.min(1,t/n.height),t}return t}))}(l.threshold,t),l}wrappedPerComponentHandler(t,o){for(let e=0;e<this.perComponentIOArray.length;e++){let r=this.perComponentIOArray[e];r.io==o&&t.forEach((t=>{t.target==r.el&&r.fn(t)}))}}addPerComponentFn(t,o,e){let n=this.perComponentIOArray.find((o=>o.el==t));if(n&&n.config){if(n.config.rootMargin===e.rootMargin&&n.config.root===e.root&&n.config.threshold===e.threshold)return n.fn=o,n.ioActions}else{if(n&&!n.config&&!e)return n.fn=o,n.ioActions;if(n)return this.replaceComponentFn(t,o,e)}if(l(t.getAttribute("data-scroll-id")))return void r.warn("cannot attach scroller since already exists a handler");t.setAttribute("data-scroll-id",this.i),t.setAttribute("data-scroll-multi","true"),this.i++;var i=this.buildOptions(t,e);let s=new IntersectionObserver(this.wrappedPerComponentHandler,i);s.observe(t);let h={pause:()=>{this.pauseTrackingFn(t,s)},resume:()=>{this.resumeTrackingFn(t,s)}};return this.perComponentIOArray.push({io:s,el:t,fn:o,config:e,ioActions:h}),h}addTrackingFn(t,o){var e;if(!l(t.getAttribute("data-scroll-id")))return t.setAttribute("data-scroll-id",this.i),this.callbackfns[this.i]={fn:o,el:t},this.io||(this.io=new IntersectionObserver(this.onContentVisible.bind(this),{threshold:this.props.config?a(this.props.config.threshold):.5,root:null===(e=this.props.config)||void 0===e?void 0:e.root,rootMargin:this.props.config&&this.props.config.rootMargin||"0px"})),this.io.observe(t),this.i++,{pause:()=>{this.pauseTrackingFn(t,this.io)},resume:()=>{this.resumeTrackingFn(t,this.io)}};console.warn("cannot attach scroller since already exists a handler")}replaceTrackingFn(t,o){let e=t.getAttribute("data-scroll-id");l(e)?this.callbackfns[e].fn=o:console.warn("cannot replace scroll handler since no handler found")}pauseTrackingFn(t,o){o.unobserve(t)}resumeTrackingFn(t,o){l(t.getAttribute("data-scroll-id"))&&o.observe(t)}removeTrackingFn(t,o){if(o)for(let o=0;o<this.perComponentIOArray.length;o++){const e=this.perComponentIOArray[o];if(e.el===t)return e.io.unobserve(t),void this.perComponentIOArray.splice(o,1)}else this.io.unobserve(t)}render(){let o={addToSingleio:this.addTrackingFn,addToMultipleio:this.addPerComponentFn,updateMultipleio:this.replaceComponentFn,removeTracking:this.removeTrackingFn,sensorType:"io"};return t.jsx(h.Provider,Object.assign({value:o},{children:this.props.children}),void 0)}}c.propTypes={config:s.default.shape({threshold:s.default.oneOfType([s.default.number,s.default.string]),root:s.default.instanceOf(HTMLElement),rootMargin:s.default.oneOfType([s.default.string,s.default.array])})};const d=r.isRafAvailable();exports.default=c,exports.useScrollSense=function(t=!1){const e=o.useContext(h),n=o.useRef({});if(!e)throw new Error("No intersection observer sensor has found. Did you add ScrollSense provider component?");return e&&"io"!==e.sensorType&&r.error(r.errorStrings.ioConnectWithWrongProvider),o.useMemo((()=>({onIntersection:(o,i,s)=>{if(!e)return r.error(r.errorStrings.noScrollProvider),null;let l=o.getAttribute("data-scroll-id");if(n.current[l]&&n.current[l].fn!=i)return n.current[l].fn=i,n.current[l].sensorProxy;let h=null;return h=t?e.addToMultipleio(o,(t=>{let o=n.current[t.target.getAttribute("data-scroll-id")].fn;d?window.requestAnimationFrame((e=>{o(t)})):o(t)}),s):e.addToSingleio(o,(t=>{let o=n.current[t.target.getAttribute("data-scroll-id")].fn;d?window.requestAnimationFrame((e=>{o(t)})):o(t)}),s),l=o.getAttribute("data-scroll-id"),n.current[l]={fn:i,sensorProxy:h},h},detach:o=>{e.removeTracking(o,t)}})),[e])},exports.withScrollSense=function(o){return{viaCallback:function(e,n=!1){return n?function(o,e){var n;return n=class extends i.default.Component{constructor(t){super(t),this.isComplete=!1,this.isRafAvailable=r.isRafAvailable(),this.config=null,this.ioRecords=[],this.onIntersection=this.onIntersection.bind(this),this.config={threshold:e&&e.threshold||.5,root:null==e?void 0:e.root,rootMargin:e&&e.rootMargin||"0px"},this.props.threshold&&(this.config.threshold=this.props.threshold),void 0!==this.props.root&&(this.config.root=this.props.root),this.props.rootMargin&&(this.config.rootMargin=this.props.rootMargin)}onIntersection(t,o,e){if(!this.isComplete)return void r.warn("Component still not mounted. To add an element to the tracking list, element must be mounted");let n=!1,i=!1,s=!1,l=Object.assign({},this.config);return e&&e.threshold&&(l.threshold=e.threshold,n=!0),e&&void 0!==e.root&&(l.root=e.root,i=!0),e&&e.rootMargin&&(l.rootMargin=e.rootMargin,s=!0),t?(this.ioRecords.push({el:t,fn:o,config:l,flags:{isRootMarginSet:s,isRootSet:i,isThresholdSet:n}}),this.context.addToMultipleio(t,(e=>{this.isRafAvailable?window.requestAnimationFrame((r=>{o(e,t,r)})):o(e,t)}),{threshold:this.config.threshold,root:this.config.root,rootMargin:this.config.rootMargin})):(r.warn("ScrollSense: There is no dom element to attach the scroll sense"),{})}updateIObservers(t,o,e){for(let r=0;r<this.ioRecords.length;r++){const n=this.ioRecords[r];this.context.updateMultipleio(n.el,(t=>{this.isRafAvailable?window.requestAnimationFrame((o=>{n.fn(t,n.el,o)})):n.fn(t,n.el)}),{threshold:n.flags.isThresholdSet?n.config.threshold:n.config.threshold=t,root:n.flags.isRootSet?n.config.root:n.config.root=o,rootMargin:n.flags.isRootMarginSet?n.config.rootMargin:n.config.rootMargin=e})}}componentDidUpdate(t){let o=!1;void 0!==this.props.root&&t.root!=this.props.root&&(this.config.root=this.props.root,o=!0),this.props.threshold&&t.threshold!=this.props.threshold&&(this.config.threshold=this.props.threshold,o=!0),this.props.rootMargin&&t.rootMargin!=this.props.rootMargin&&(this.config.rootMargin=this.props.rootMargin,o=!0),o&&this.updateIObservers(this.config.threshold,this.config.root,this.config.rootMargin)}componentDidMount(){this.isComplete=!0}render(){return t.jsx(o,Object.assign({},this.props,{onIntersection:this.onIntersection}),void 0)}},n.contextType=h,n}(o,e):function(o){var e;return(e=class extends i.default.Component{constructor(t){super(t),this.isRafAvailable=r.isRafAvailable(),this.isComplete=!1,this.onIntersection=this.onIntersection.bind(this)}onIntersection(t,o){if(this.isComplete)return this.context.addToSingleio(t,(e=>{this.isRafAvailable?window.requestAnimationFrame((r=>{o(e,t,r)})):o(e,t)}));r.warn("Component still not mounted. To add an element to the tracking list, element must be mounted")}componentDidMount(){this.isComplete=!0}render(){return t.jsx(o,Object.assign({},this.props,{onIntersection:this.onIntersection}),void 0)}}).contextType=h,e}(o)},viaProps:function(e,n,s=!1){return s?function(o,e,n){var s;return(s=class extends i.default.Component{constructor(t){super(t),this.config=null,this.ref=i.default.createRef(),e||(e=t=>({scrollInfo:t})),this.state={scrollInfo:{isIntersecting:!1},sensorProxy:null},this.config={threshold:n&&n.threshold||.5,root:null==n?void 0:n.root,rootMargin:n&&n.rootMargin||"0px"},this.props.threshold&&(this.config.threshold=this.props.threshold),void 0!==this.props.root&&(this.config.root=this.props.root),this.props.rootMargin&&(this.config.rootMargin=this.props.rootMargin)}attachIObserver(t,o,e){let n=this,i=this.ref.current.children[0];if(i){const r=this.context.addToMultipleio(i,(t=>{n.setState({scrollInfo:t})}),{threshold:t,root:o,rootMargin:e});this.setState({sensorProxy:r})}else r.warn("ScrollSense: There is no dom element to attach the scroll sense")}updateIObserver(t,o,e){let n=this,i=this.ref.current.children[0];i?this.context.updateMultipleio(i,(t=>{n.setState({scrollInfo:t})}),{threshold:t,root:o,rootMargin:e}):r.warn("ScrollSense: There is no dom element to attach the scroll sense")}componentDidUpdate(t){let o=!1;void 0!==this.props.root&&t.root!=this.props.root&&(this.config.root=this.props.root,o=!0),this.props.threshold&&t.threshold!=this.props.threshold&&(this.config.threshold=this.props.threshold,o=!0),this.props.rootMargin&&t.rootMargin!=this.props.rootMargin&&(this.config.rootMargin=this.props.rootMargin,o=!0),o&&this.updateIObserver(this.config.threshold,this.config.root,this.config.rootMargin)}componentDidMount(){this.attachIObserver(this.config.threshold,this.config.root,this.config.rootMargin)}render(){let r=e(this.state.scrollInfo);return t.jsx("div",Object.assign({ref:this.ref},{children:t.jsx(o,Object.assign({},this.props,r,this.state.sensorProxy),void 0)}),void 0)}}).contextType=h,s}(o,n,e):function(o,e){var n;return(n=class extends i.default.Component{constructor(t){super(t),this.ref=i.default.createRef(),e||(e=t=>({scrollInfo:t})),this.state={scrollInfo:{isIntersecting:!1},sensorProxy:null}}componentDidMount(){let t=this,o=this.ref.current.children[0];if(o){const e=this.context.addToSingleio(o,(o=>{console.log("s",o),t.setState({scrollInfo:o})}));this.setState({sensorProxy:e})}else r.warn("There is no dom element to attach the scroll sense")}render(){let r=e(this.state.scrollInfo);return t.jsx("div",Object.assign({ref:this.ref},{children:t.jsx(o,Object.assign({},this.props,r,this.state.sensorProxy),void 0)}),void 0)}}).contextType=h,n}(o,n)}}};
//# sourceMappingURL=index.js.map