@pronotron/io
Version:
Reliable viewport tracking without missed targets, unlike the default IntersectionObserver API.
1 lines • 3.09 kB
JavaScript
import{NativeControlTable as t,IDPool as s}from"@pronotron/utils";var i=class{constructor(i=20,e=!0){this.t=new Map,this.i=new Map,this.h=0,this.o=0,this.l=0,this.u=0,this.p=0,this.v=0,this._=0,this.m=e,this.N=new t(11,e?Uint16Array:Float32Array,i),this.A=new s(i)}addNode(t){if(this.t.has(t.ref))return console.warn("Node is already in the list.",t.ref),!1;{const s=this.A.get();this.t.set(t.ref,s),this.i.set(s,t);const i=this.F(t.dispatch.onFastForward);return this.N.add(s,{0:s,1:0,2:0,3:0,4:0,5:t.dispatch.onInViewport?1:0,6:t.dispatch[this.k.I]?1:0,7:t.dispatch[this.k.B]?1:0,8:t.dispatch[this.k.L]?1:0,9:t.dispatch[this.k.M]?1:0,10:i}),this.A.consume(s),this.P(s,t),s}}removeNode(t){const s=this.t.get(t);void 0!==s?this.T([s]):console.warn("IONode is not found in the list.",t)}setLastScroll(t){this.h=t}updatePositions(t){this._=t,this.S(),this.i.forEach((t,s)=>this.P(s,t))}updateViewportLayout(t,s){s<=t&&console.warn("Tracking area must be bigger than 0 units"),this.o=t,this.l=s,this.v=s-t}U(t,s){return s<this.u?1:t>this.p?3:2}T(t){for(const s of t){const t=this.i.get(s);this.t.delete(t.ref),this.i.delete(s),this.N.remove(s),this.A.release(s),t.onRemoveNode&&t.onRemoveNode()}}P(t,s){const{start:i,end:e}=s.getBounds(),h=s.offset||0,n=this.m?Math.round(i-h):i-h,o=this.m?Math.round(e+h):e+h;this.N.modifyByID(t,{1:n,2:o})}F(t){switch(t){case"skip_both":default:return 0;case"execute_both":return 1;case"execute_last":return 2}}O(){this.u=this.o+this.h,this.p=this.l+this.h}S(){if(this.m&&this._>65535&&this.N.table.constructor!==Uint32Array){const t=Uint32Array.from(this.N.table);this.N.table=t}}},e=class extends i{constructor(){super(...arguments),this.R={2:{1:(t,s)=>{this.V(t,s,7,this.k.B)},3:(t,s)=>{this.V(t,s,9,this.k.M)}},1:{2:(t,s)=>{this.V(t,s,6,this.k.I)},3:(t,s)=>{this.C(t,s,6,this.k.I,9,this.k.M)}},3:{2:(t,s)=>{this.V(t,s,8,this.k.L)},1:(t,s)=>{this.C(t,s,8,this.k.L,7,this.k.B)}}}}handleScroll(t){this.direction=t>this.h?this.q.j:this.q.D,this.h=t,this.O(),this.G()}G(){const{table:t,stride:s,usedSlots:i}=this.N;for(let e=0;e<i;e++){const i=e*s,h=t[i+0],n=t[i+1],o=t[i+2],r=t[i+4],a=this.U(n,o);if(r!==a&&(0!==r&&this.R[r][a](i,h),this.N.modifyByPosition(e,{4:a,3:2===a?1:0})),t[i+5]&&t[i+3]){const t=this.H(n,o,this.h,this.v);this.J(h,t)}}}V(t,s,i,e){const h=this.N.table;h[t+i]&&(h[t+i]=this.K(s,e))}C(t,s,i,e,h,n){const o=this.N.table[t+10];if(0!==o)switch(o){case 2:this.V(t,s,h,n);break;case 1:this.V(t,s,i,e),this.V(t,s,h,n)}}H(t,s,i,e){return 2*(s-i)/(e+(s-t))-1}J(t,s){this.i.get(t).dispatch.onInViewport(s)}K(t,s){const i=this.i.get(t).dispatch[s];return"limit"in i?(i.dispatch(),i.limit-=1,i.limit<1?0:1):(i(),1)}},h=class extends e{constructor(){super(...arguments),this.direction="down",this.q={j:"down",D:"up"},this.k={I:"onTopEnter",B:"onTopExit",L:"onBottomEnter",M:"onBottomExit"}}},n=class extends e{constructor(){super(...arguments),this.direction="right",this.q={j:"left",D:"right"},this.k={I:"onLeftEnter",B:"onLeftExit",L:"onRightEnter",M:"onRightExit"}}};export{n as PronotronIOHorizontalObserver,h as PronotronIOVerticalObserver};