@embedpdf/plugin-scroll 1.3.4 → 1.3.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +1 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +59 -1
- package/dist/index.js.map +1 -1
- package/dist/lib/actions.d.ts +8 -2
- package/dist/lib/reducer.d.ts +2 -1
- package/dist/lib/scroll-plugin.d.ts +4 -1
- package/dist/lib/types.d.ts +10 -0
- package/package.json +6 -6
package/dist/index.cjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const t=require("@embedpdf/core"),e=require("@embedpdf/models");var i=(t=>(t.Vertical="vertical",t.Horizontal="horizontal",t))(i||{});class r{constructor(t){this.pageGap=t.pageGap??20,this.viewportGap=t.viewportGap??20,this.bufferSize=t.bufferSize??2}getVisibleRange(t,e,i){const r=this.getScrollOffset(t),a=r,s=r+this.getClientSize(t);let o=0;for(;o<e.length&&(e[o].offset+e[o].height)*i<=a;)o++;let n=o;for(;n<e.length&&e[n].offset*i<=s;)n++;return{start:Math.max(0,o-this.bufferSize),end:Math.min(e.length-1,n+this.bufferSize-1)}}handleScroll(t,e,i){const r=this.getVisibleRange(t,e,i),a=e.slice(r.start,r.end+1),s=this.calculatePageVisibility(a,t,i),o=s.map((t=>t.pageNumber)),n=e.slice(r.start,r.end+1).flatMap((t=>t.index)),h=this.determineCurrentPage(s),l=e[r.start],g=e[r.end],c=l?l.offset*i:0,u=g?(e[e.length-1].offset+e[e.length-1].height)*i-(g.offset+g.height)*i:0;return{currentPage:h,visiblePages:o,pageVisibilityMetrics:s,renderedPageIndexes:n,scrollOffset:{x:t.scrollLeft,y:t.scrollTop},startSpacing:c,endSpacing:u}}calculatePageVisibility(t,e,i){const r=[];return t.forEach((t=>{t.pageLayouts.forEach((a=>{const s=t.x*i,o=t.y*i,n=s+a.x*i,h=o+a.y*i,l=a.rotatedWidth*i,g=a.rotatedHeight*i,c=e.scrollLeft,u=e.scrollTop,p=c+e.clientWidth,d=u+e.clientHeight,m=Math.max(n,c),y=Math.max(h,u),S=Math.min(n+l,p),P=Math.min(h+g,d);if(m<S&&y<P){const t=S-m,e=P-y,s=l*g,o=t*e;r.push({pageNumber:a.pageNumber,viewportX:m-c,viewportY:y-u,visiblePercentage:o/s*100,original:{pageX:(m-n)/i,pageY:(y-h)/i,visibleWidth:t/i,visibleHeight:e/i,scale:1},scaled:{pageX:m-n,pageY:y-h,visibleWidth:t,visibleHeight:e,scale:i}})}}))})),r}determineCurrentPage(t){if(0===t.length)return 1;const e=Math.max(...t.map((t=>t.visiblePercentage))),i=t.filter((t=>t.visiblePercentage===e));return 1===i.length?i[0].pageNumber:i.sort(((t,e)=>t.pageNumber-e.pageNumber))[0].pageNumber}getRectLocationForPage(t,e,i){const r=e.find((e=>e.pageNumbers.includes(t)));if(!r)return null;const a=r.pageLayouts.find((e=>e.pageNumber===t));if(!a)return null;let s=0;if(i){const t=i.width;r.width<t&&(s=(t-r.width)/2)}return{origin:{x:r.x+a.x+s,y:r.y+a.y},size:{width:a.width,height:a.height}}}getScrollPositionForPage(t,i,r,a,s){const o=this.getTotalContentSize(i),n=this.getRectLocationForPage(t,i,o);if(!n)return null;const h=e.scalePosition(n.origin,r);if(s){const t=e.transformPosition({width:n.size.width,height:n.size.height},{x:s.x,y:s.y},a,r);return{x:h.x+t.x+this.viewportGap,y:h.y+t.y+this.viewportGap}}return{x:h.x+this.viewportGap,y:h.y+this.viewportGap}}getRectPositionForPage(t,i,r,a,s){const o=this.getTotalContentSize(i),n=this.getRectLocationForPage(t,i,o);if(!n)return null;const h=e.scalePosition(n.origin,r),l=e.transformRect({width:n.size.width,height:n.size.height},s,a,r);return{origin:{x:h.x+l.origin.x,y:h.y+l.origin.y},size:l.size}}}class a extends r{constructor(t){super(t)}createVirtualItems(t){let e=0;return t.map(((t,i)=>{let r=0;const a=t.map((t=>{const e={pageNumber:t.index+1,pageIndex:t.index,x:r,y:0,width:t.size.width,height:t.size.height,rotatedWidth:t.rotatedSize.width,rotatedHeight:t.rotatedSize.height};return r+=t.rotatedSize.width+this.pageGap,e})),s=t.reduce(((e,i,r)=>e+i.rotatedSize.width+(r<t.length-1?this.pageGap:0)),0),o=Math.max(...t.map((t=>t.rotatedSize.height))),n={id:`item-${i}`,x:0,y:e,offset:e,width:s,height:o,pageLayouts:a,pageNumbers:t.map((t=>t.index+1)),index:i};return e+=o+this.pageGap,n}))}getTotalContentSize(t){if(0===t.length)return{width:0,height:0};return{width:Math.max(...t.map((t=>t.width))),height:t[t.length-1].y+t[t.length-1].height}}getScrollOffset(t){return t.scrollTop}getClientSize(t){return t.clientHeight}}class s extends r{constructor(t){super(t)}createVirtualItems(t){let e=0;return t.map(((t,i)=>{let r=0;const a=t.map((t=>{const e={pageNumber:t.index+1,pageIndex:t.index,x:r,y:0,width:t.size.width,height:t.size.height,rotatedWidth:t.rotatedSize.width,rotatedHeight:t.rotatedSize.height};return r+=t.rotatedSize.width+this.pageGap,e})),s=t.reduce(((e,i,r)=>e+i.rotatedSize.width+(r<t.length-1?this.pageGap:0)),0),o=Math.max(...t.map((t=>t.rotatedSize.height))),n={id:`item-${i}`,x:e,y:0,offset:e,width:s,height:o,pageLayouts:a,pageNumbers:t.map((t=>t.index+1)),index:i};return e+=s+this.pageGap,n}))}getTotalContentSize(t){if(0===t.length)return{width:0,height:0};return{width:t[t.length-1].x+t[t.length-1].width,height:Math.max(...t.map((t=>t.height)))}}getScrollOffset(t){return t.scrollLeft}getClientSize(t){return t.clientWidth}}const o="UPDATE_SCROLL_STATE",n="UPDATE_TOTAL_PAGES";function h(t){return{type:o,payload:t}}const l=class extends t.BasePlugin{constructor(r,o,h){var l,g,c,u;super(r,o),this.id=r,this.config=h,this.currentScale=1,this.currentRotation=e.Rotation.Degree0,this.currentPage=1,this.layoutReady=!1,this.layout$=t.createBehaviorEmitter(),this.scroll$=t.createBehaviorEmitter(),this.state$=t.createBehaviorEmitter(),this.scrollerLayout$=t.createBehaviorEmitter(),this.pageChange$=t.createBehaviorEmitter(),this.layoutReady$=t.createBehaviorEmitter(),this.viewport=this.registry.getPlugin("viewport").provides(),this.strategyConfig={pageGap:(null==(l=this.config)?void 0:l.pageGap)??10,viewportGap:this.viewport.getViewportGap(),bufferSize:(null==(g=this.config)?void 0:g.bufferSize)??2},this.strategy=(null==(c=this.config)?void 0:c.strategy)===i.Horizontal?new s(this.strategyConfig):new a(this.strategyConfig),this.initialPage=null==(u=this.config)?void 0:u.initialPage,this.currentScale=this.coreState.core.scale,this.currentRotation=this.coreState.core.rotation,this.viewport.onViewportChange((t=>this.commitMetrics(this.computeMetrics(t))),{mode:"throttle",wait:100}),this.coreStore.onAction(t.SET_DOCUMENT,((e,i)=>{const r=i.core.pages.length;this.dispatch({type:n,payload:r}),this.pageChange$.emit({pageNumber:this.currentPage,totalPages:r}),this.refreshAll(t.getPagesWithRotatedSize(i.core),this.viewport.getMetrics())})),this.coreStore.onAction(t.SET_ROTATION,((e,i)=>this.refreshAll(t.getPagesWithRotatedSize(i.core),this.viewport.getMetrics()))),this.coreStore.onAction(t.SET_PAGES,((e,i)=>this.refreshAll(t.getPagesWithRotatedSize(i.core),this.viewport.getMetrics())))}computeLayout(t){const e=this.strategy.createVirtualItems(t);return{virtualItems:e,totalContentSize:this.strategy.getTotalContentSize(e)}}computeMetrics(t,e=this.state.virtualItems){return this.strategy.handleScroll(t,e,this.currentScale)}commit(t,e){this.dispatch(h(t)),(null==e?void 0:e.layout)&&this.layout$.emit(e.layout),(null==e?void 0:e.metrics)&&(this.scroll$.emit(e.metrics),e.metrics.currentPage!==this.currentPage&&(this.currentPage=e.metrics.currentPage,this.pageChange$.emit({pageNumber:this.currentPage,totalPages:this.state.totalPages}))),this.scrollerLayout$.emit(this.getScrollerLayout())}commitMetrics(t){this.commit(t,{metrics:t})}refreshAll(t,e){const i=this.computeLayout(t),r=this.computeMetrics(e,i.virtualItems);this.commit({...i,...r},{layout:i,metrics:r})}getVirtualItemsFromState(){return this.state.virtualItems||[]}onScrollerData(t){return this.scrollerLayout$.on(t)}getScrollerLayout(){const t=this.coreState.core.scale;return((t,e)=>({startSpacing:t.startSpacing,endSpacing:t.endSpacing,totalWidth:t.totalContentSize.width*e,totalHeight:t.totalContentSize.height*e,pageGap:t.pageGap*e,strategy:t.strategy,items:t.renderedPageIndexes.map((i=>({...t.virtualItems[i],pageLayouts:t.virtualItems[i].pageLayouts.map((t=>({...t,rotatedWidth:t.rotatedWidth*e,rotatedHeight:t.rotatedHeight*e,width:t.width*e,height:t.height*e})))})))}))(this.state,t)}pushScrollLayout(){this.scrollerLayout$.emit(this.getScrollerLayout())}onStoreUpdated(t,e){this.pushScrollLayout()}onCoreStoreUpdated(t,e){t.core.scale!==e.core.scale&&(this.currentScale=e.core.scale,this.commitMetrics(this.computeMetrics(this.viewport.getMetrics()))),t.core.rotation!==e.core.rotation&&(this.currentRotation=e.core.rotation)}setScrollStrategy(e){if(e===i.Horizontal&&this.strategy instanceof s||e===i.Vertical&&this.strategy instanceof a)return;this.strategy=e===i.Horizontal?new s(this.strategyConfig):new a(this.strategyConfig),this.dispatch(h({strategy:e}));const r=t.getPagesWithRotatedSize(this.coreState.core);this.refreshAll(r,this.viewport.getMetrics())}setLayoutReady(){this.layoutReady||(this.layoutReady=!0,this.layoutReady$.emit(!0),this.initialPage&&this.scrollToPage({pageNumber:this.initialPage,behavior:"instant"}))}buildCapability(){return{onStateChange:this.state$.on,onLayoutChange:this.layout$.on,onScroll:this.scroll$.on,onPageChange:this.pageChange$.on,onLayoutReady:this.layoutReady$.on,getCurrentPage:()=>this.currentPage,getTotalPages:()=>this.state.totalPages,scrollToPage:this.scrollToPage.bind(this),scrollToNextPage:this.scrollToNextPage.bind(this),scrollToPreviousPage:this.scrollToPreviousPage.bind(this),getMetrics:this.getMetrics.bind(this),getLayout:this.getLayout.bind(this),getRectPositionForPage:this.getRectPositionForPage.bind(this),getPageGap:()=>this.state.pageGap,setScrollStrategy:t=>this.setScrollStrategy(t)}}scrollToPage(t){const{pageNumber:e,behavior:i="smooth",pageCoordinates:r,center:a=!1}=t,s=this.getVirtualItemsFromState(),o=this.strategy.getScrollPositionForPage(e,s,this.currentScale,this.currentRotation,r);o&&this.viewport.scrollTo({...o,behavior:i,center:a})}scrollToNextPage(t="smooth"){const e=this.getVirtualItemsFromState(),i=e.findIndex((t=>t.pageNumbers.includes(this.currentPage)));if(i>=0&&i<e.length-1){const r=e[i+1],a=this.strategy.getScrollPositionForPage(r.pageNumbers[0],e,this.currentScale,this.currentRotation);a&&this.viewport.scrollTo({...a,behavior:t})}}scrollToPreviousPage(t="smooth"){const e=this.getVirtualItemsFromState(),i=e.findIndex((t=>t.pageNumbers.includes(this.currentPage)));if(i>0){const r=e[i-1],a=this.strategy.getScrollPositionForPage(r.pageNumbers[0],e,this.currentScale,this.currentRotation);a&&this.viewport.scrollTo({...a,behavior:t})}}getMetrics(t){const e=t||this.viewport.getMetrics(),i=this.getVirtualItemsFromState();return this.strategy.handleScroll(e,i,this.currentScale)}getLayout(){return{virtualItems:this.state.virtualItems,totalContentSize:this.state.totalContentSize}}getRectPositionForPage(t,e,i,r){return this.strategy.getRectPositionForPage(t+1,this.state.virtualItems,i??this.currentScale,r??this.currentRotation,e)}async initialize(){}async destroy(){this.layout$.clear(),this.scroll$.clear(),this.pageChange$.clear(),this.state$.clear(),this.scrollerLayout$.clear(),this.layoutReady$.clear(),super.destroy()}};l.id="scroll";let g=l;const c="scroll",u={id:c,name:"Scroll Plugin",version:"1.0.0",provides:["scroll"],requires:["viewport"],optional:[],defaultConfig:{enabled:!0,pageGap:10}},p={currentPage:1,visiblePages:[],pageVisibilityMetrics:[],renderedPageIndexes:[],scrollOffset:{x:0,y:0},startSpacing:0,endSpacing:0},d={manifest:u,create:(t,e)=>new g(c,t,e),reducer:(e,i)=>{switch(i.type){case n:return{...e,totalPages:i.payload};case t.SET_SCALE:return{...e,scale:i.payload};case o:return{...e,...i.payload};case"SET_DESIRED_SCROLL_POSITION":return{...e,desiredScrollPosition:i.payload};default:return e}},initialState:(t,e)=>((t,e)=>({virtualItems:[],totalPages:t.pages.length,totalContentSize:{width:0,height:0},desiredScrollPosition:{x:0,y:0},strategy:e.strategy??i.Vertical,pageGap:e.pageGap??10,scale:t.scale,...p}))(t,e)};exports.SCROLL_PLUGIN_ID=c,exports.ScrollPlugin=g,exports.ScrollPluginPackage=d,exports.ScrollStrategy=i,exports.manifest=u;
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const t=require("@embedpdf/core"),e=require("@embedpdf/models");var i=(t=>(t.Vertical="vertical",t.Horizontal="horizontal",t))(i||{});class a{constructor(t){this.pageGap=t.pageGap??20,this.viewportGap=t.viewportGap??20,this.bufferSize=t.bufferSize??2}getVisibleRange(t,e,i){const a=this.getScrollOffset(t),r=a,s=a+this.getClientSize(t);let o=0;for(;o<e.length&&(e[o].offset+e[o].height)*i<=r;)o++;let h=o;for(;h<e.length&&e[h].offset*i<=s;)h++;return{start:Math.max(0,o-this.bufferSize),end:Math.min(e.length-1,h+this.bufferSize-1)}}handleScroll(t,e,i){const a=this.getVisibleRange(t,e,i),r=e.slice(a.start,a.end+1),s=this.calculatePageVisibility(r,t,i),o=s.map((t=>t.pageNumber)),h=e.slice(a.start,a.end+1).flatMap((t=>t.index)),n=this.determineCurrentPage(s),g=e[a.start],l=e[a.end],c=g?g.offset*i:0,u=l?(e[e.length-1].offset+e[e.length-1].height)*i-(l.offset+l.height)*i:0;return{currentPage:n,visiblePages:o,pageVisibilityMetrics:s,renderedPageIndexes:h,scrollOffset:{x:t.scrollLeft,y:t.scrollTop},startSpacing:c,endSpacing:u}}calculatePageVisibility(t,e,i){const a=[];return t.forEach((t=>{t.pageLayouts.forEach((r=>{const s=t.x*i,o=t.y*i,h=s+r.x*i,n=o+r.y*i,g=r.rotatedWidth*i,l=r.rotatedHeight*i,c=e.scrollLeft,u=e.scrollTop,p=c+e.clientWidth,d=u+e.clientHeight,m=Math.max(h,c),S=Math.max(n,u),y=Math.min(h+g,p),P=Math.min(n+l,d);if(m<y&&S<P){const t=y-m,e=P-S,s=g*l,o=t*e;a.push({pageNumber:r.pageNumber,viewportX:m-c,viewportY:S-u,visiblePercentage:o/s*100,original:{pageX:(m-h)/i,pageY:(S-n)/i,visibleWidth:t/i,visibleHeight:e/i,scale:1},scaled:{pageX:m-h,pageY:S-n,visibleWidth:t,visibleHeight:e,scale:i}})}}))})),a}determineCurrentPage(t){if(0===t.length)return 1;const e=Math.max(...t.map((t=>t.visiblePercentage))),i=t.filter((t=>t.visiblePercentage===e));return 1===i.length?i[0].pageNumber:i.sort(((t,e)=>t.pageNumber-e.pageNumber))[0].pageNumber}getRectLocationForPage(t,e,i){const a=e.find((e=>e.pageNumbers.includes(t)));if(!a)return null;const r=a.pageLayouts.find((e=>e.pageNumber===t));if(!r)return null;let s=0;if(i){const t=i.width;a.width<t&&(s=(t-a.width)/2)}return{origin:{x:a.x+r.x+s,y:a.y+r.y},size:{width:r.width,height:r.height}}}getScrollPositionForPage(t,i,a,r,s){const o=this.getTotalContentSize(i),h=this.getRectLocationForPage(t,i,o);if(!h)return null;const n=e.scalePosition(h.origin,a);if(s){const t=e.transformPosition({width:h.size.width,height:h.size.height},{x:s.x,y:s.y},r,a);return{x:n.x+t.x+this.viewportGap,y:n.y+t.y+this.viewportGap}}return{x:n.x+this.viewportGap,y:n.y+this.viewportGap}}getRectPositionForPage(t,i,a,r,s){const o=this.getTotalContentSize(i),h=this.getRectLocationForPage(t,i,o);if(!h)return null;const n=e.scalePosition(h.origin,a),g=e.transformRect({width:h.size.width,height:h.size.height},s,r,a);return{origin:{x:n.x+g.origin.x,y:n.y+g.origin.y},size:g.size}}}class r extends a{constructor(t){super(t)}createVirtualItems(t){let e=0;return t.map(((t,i)=>{let a=0;const r=t.map((t=>{const e={pageNumber:t.index+1,pageIndex:t.index,x:a,y:0,width:t.size.width,height:t.size.height,rotatedWidth:t.rotatedSize.width,rotatedHeight:t.rotatedSize.height};return a+=t.rotatedSize.width+this.pageGap,e})),s=t.reduce(((e,i,a)=>e+i.rotatedSize.width+(a<t.length-1?this.pageGap:0)),0),o=Math.max(...t.map((t=>t.rotatedSize.height))),h={id:`item-${i}`,x:0,y:e,offset:e,width:s,height:o,pageLayouts:r,pageNumbers:t.map((t=>t.index+1)),index:i};return e+=o+this.pageGap,h}))}getTotalContentSize(t){if(0===t.length)return{width:0,height:0};return{width:Math.max(...t.map((t=>t.width))),height:t[t.length-1].y+t[t.length-1].height}}getScrollOffset(t){return t.scrollTop}getClientSize(t){return t.clientHeight}}class s extends a{constructor(t){super(t)}createVirtualItems(t){let e=0;return t.map(((t,i)=>{let a=0;const r=t.map((t=>{const e={pageNumber:t.index+1,pageIndex:t.index,x:a,y:0,width:t.size.width,height:t.size.height,rotatedWidth:t.rotatedSize.width,rotatedHeight:t.rotatedSize.height};return a+=t.rotatedSize.width+this.pageGap,e})),s=t.reduce(((e,i,a)=>e+i.rotatedSize.width+(a<t.length-1?this.pageGap:0)),0),o=Math.max(...t.map((t=>t.rotatedSize.height))),h={id:`item-${i}`,x:e,y:0,offset:e,width:s,height:o,pageLayouts:r,pageNumbers:t.map((t=>t.index+1)),index:i};return e+=s+this.pageGap,h}))}getTotalContentSize(t){if(0===t.length)return{width:0,height:0};return{width:t[t.length-1].x+t[t.length-1].width,height:Math.max(...t.map((t=>t.height)))}}getScrollOffset(t){return t.scrollLeft}getClientSize(t){return t.clientWidth}}const o="UPDATE_SCROLL_STATE",h="UPDATE_TOTAL_PAGES",n="SET_PAGE_CHANGE_STATE";function g(t){return{type:o,payload:t}}function l(t){return{type:n,payload:t}}const c=class extends t.BasePlugin{constructor(a,o,n){var g,l,c,u;super(a,o),this.id=a,this.config=n,this.currentScale=1,this.currentRotation=e.Rotation.Degree0,this.currentPage=1,this.layoutReady=!1,this.pageChangeState$=t.createBehaviorEmitter(),this.layout$=t.createBehaviorEmitter(),this.scroll$=t.createBehaviorEmitter(),this.state$=t.createBehaviorEmitter(),this.scrollerLayout$=t.createBehaviorEmitter(),this.pageChange$=t.createBehaviorEmitter(),this.layoutReady$=t.createBehaviorEmitter(),this.viewport=this.registry.getPlugin("viewport").provides(),this.strategyConfig={pageGap:(null==(g=this.config)?void 0:g.pageGap)??10,viewportGap:this.viewport.getViewportGap(),bufferSize:(null==(l=this.config)?void 0:l.bufferSize)??2},this.strategy=(null==(c=this.config)?void 0:c.strategy)===i.Horizontal?new s(this.strategyConfig):new r(this.strategyConfig),this.initialPage=null==(u=this.config)?void 0:u.initialPage,this.currentScale=this.coreState.core.scale,this.currentRotation=this.coreState.core.rotation,this.viewport.onScrollActivity((t=>{this.state.pageChangeState.isChanging&&!t.isSmoothScrolling&&this.completePageChange()})),this.viewport.onViewportChange((t=>this.commitMetrics(this.computeMetrics(t))),{mode:"throttle",wait:100}),this.coreStore.onAction(t.SET_DOCUMENT,((e,i)=>{const a=i.core.pages.length;this.dispatch({type:h,payload:a}),this.pageChange$.emit({pageNumber:this.currentPage,totalPages:a}),this.refreshAll(t.getPagesWithRotatedSize(i.core),this.viewport.getMetrics())})),this.coreStore.onAction(t.SET_ROTATION,((e,i)=>this.refreshAll(t.getPagesWithRotatedSize(i.core),this.viewport.getMetrics()))),this.coreStore.onAction(t.SET_PAGES,((e,i)=>this.refreshAll(t.getPagesWithRotatedSize(i.core),this.viewport.getMetrics())))}startPageChange(t,e="smooth"){const i={isChanging:!0,targetPage:t,fromPage:this.currentPage,startTime:Date.now()};this.dispatch(l(i)),"instant"===e&&this.completePageChange()}completePageChange(){if(!this.state.pageChangeState.isChanging)return;const t={isChanging:!1,targetPage:this.state.pageChangeState.targetPage,fromPage:this.state.pageChangeState.fromPage,startTime:this.state.pageChangeState.startTime};this.dispatch(l(t))}computeLayout(t){const e=this.strategy.createVirtualItems(t);return{virtualItems:e,totalContentSize:this.strategy.getTotalContentSize(e)}}computeMetrics(t,e=this.state.virtualItems){return this.strategy.handleScroll(t,e,this.currentScale)}commit(t,e){this.dispatch(g(t)),(null==e?void 0:e.layout)&&this.layout$.emit(e.layout),(null==e?void 0:e.metrics)&&(this.scroll$.emit(e.metrics),e.metrics.currentPage!==this.currentPage&&(this.currentPage=e.metrics.currentPage,this.pageChange$.emit({pageNumber:this.currentPage,totalPages:this.state.totalPages}))),this.scrollerLayout$.emit(this.getScrollerLayout())}commitMetrics(t){this.commit(t,{metrics:t})}refreshAll(t,e){const i=this.computeLayout(t),a=this.computeMetrics(e,i.virtualItems);this.commit({...i,...a},{layout:i,metrics:a})}getVirtualItemsFromState(){return this.state.virtualItems||[]}onScrollerData(t){return this.scrollerLayout$.on(t)}getScrollerLayout(){const t=this.coreState.core.scale;return((t,e)=>({startSpacing:t.startSpacing,endSpacing:t.endSpacing,totalWidth:t.totalContentSize.width*e,totalHeight:t.totalContentSize.height*e,pageGap:t.pageGap*e,strategy:t.strategy,items:t.renderedPageIndexes.map((i=>({...t.virtualItems[i],pageLayouts:t.virtualItems[i].pageLayouts.map((t=>({...t,rotatedWidth:t.rotatedWidth*e,rotatedHeight:t.rotatedHeight*e,width:t.width*e,height:t.height*e})))})))}))(this.state,t)}pushScrollLayout(){this.scrollerLayout$.emit(this.getScrollerLayout())}onStoreUpdated(t,e){this.pushScrollLayout(),t.pageChangeState!==e.pageChangeState&&this.pageChangeState$.emit(e.pageChangeState)}onCoreStoreUpdated(t,e){t.core.scale!==e.core.scale&&(this.currentScale=e.core.scale,this.commitMetrics(this.computeMetrics(this.viewport.getMetrics()))),t.core.rotation!==e.core.rotation&&(this.currentRotation=e.core.rotation)}setScrollStrategy(e){if(e===i.Horizontal&&this.strategy instanceof s||e===i.Vertical&&this.strategy instanceof r)return;this.strategy=e===i.Horizontal?new s(this.strategyConfig):new r(this.strategyConfig),this.dispatch(g({strategy:e}));const a=t.getPagesWithRotatedSize(this.coreState.core);this.refreshAll(a,this.viewport.getMetrics())}setLayoutReady(){this.layoutReady||(this.layoutReady=!0,this.layoutReady$.emit(!0),this.initialPage&&this.scrollToPage({pageNumber:this.initialPage,behavior:"instant"}))}buildCapability(){return{onStateChange:this.state$.on,onLayoutChange:this.layout$.on,onScroll:this.scroll$.on,onPageChange:this.pageChange$.on,onLayoutReady:this.layoutReady$.on,onPageChangeState:this.pageChangeState$.on,getCurrentPage:()=>this.currentPage,getTotalPages:()=>this.state.totalPages,getPageChangeState:()=>this.state.pageChangeState,scrollToPage:this.scrollToPage.bind(this),scrollToNextPage:this.scrollToNextPage.bind(this),scrollToPreviousPage:this.scrollToPreviousPage.bind(this),getMetrics:this.getMetrics.bind(this),getLayout:this.getLayout.bind(this),getRectPositionForPage:this.getRectPositionForPage.bind(this),getPageGap:()=>this.state.pageGap,setScrollStrategy:t=>this.setScrollStrategy(t)}}scrollToPage(t){const{pageNumber:e,behavior:i="smooth",pageCoordinates:a,center:r=!1}=t;this.startPageChange(e,i);const s=this.getVirtualItemsFromState(),o=this.strategy.getScrollPositionForPage(e,s,this.currentScale,this.currentRotation,a);o?this.viewport.scrollTo({...o,behavior:i,center:r}):this.completePageChange()}scrollToNextPage(t="smooth"){const e=this.getVirtualItemsFromState(),i=e.findIndex((t=>t.pageNumbers.includes(this.currentPage)));if(i>=0&&i<e.length-1){const a=e[i+1],r=a.pageNumbers[0];this.startPageChange(r,t);const s=this.strategy.getScrollPositionForPage(a.pageNumbers[0],e,this.currentScale,this.currentRotation);s?this.viewport.scrollTo({...s,behavior:t}):this.completePageChange()}}scrollToPreviousPage(t="smooth"){const e=this.getVirtualItemsFromState(),i=e.findIndex((t=>t.pageNumbers.includes(this.currentPage)));if(i>0){const a=e[i-1],r=a.pageNumbers[0];this.startPageChange(r,t);const s=this.strategy.getScrollPositionForPage(a.pageNumbers[0],e,this.currentScale,this.currentRotation);s?this.viewport.scrollTo({...s,behavior:t}):this.completePageChange()}}getMetrics(t){const e=t||this.viewport.getMetrics(),i=this.getVirtualItemsFromState();return this.strategy.handleScroll(e,i,this.currentScale)}getLayout(){return{virtualItems:this.state.virtualItems,totalContentSize:this.state.totalContentSize}}getRectPositionForPage(t,e,i,a){return this.strategy.getRectPositionForPage(t+1,this.state.virtualItems,i??this.currentScale,a??this.currentRotation,e)}async initialize(){}async destroy(){this.layout$.clear(),this.scroll$.clear(),this.pageChange$.clear(),this.state$.clear(),this.scrollerLayout$.clear(),this.layoutReady$.clear(),this.pageChangeState$.clear(),super.destroy()}};c.id="scroll";let u=c;const p="scroll",d={id:p,name:"Scroll Plugin",version:"1.0.0",provides:["scroll"],requires:["viewport"],optional:[],defaultConfig:{enabled:!0,pageGap:10}},m={currentPage:1,visiblePages:[],pageVisibilityMetrics:[],renderedPageIndexes:[],scrollOffset:{x:0,y:0},startSpacing:0,endSpacing:0},S={isChanging:!1,targetPage:1,fromPage:1,startTime:0},y={manifest:d,create:(t,e)=>new u(p,t,e),reducer:(e,i)=>{switch(i.type){case h:return{...e,totalPages:i.payload};case t.SET_SCALE:return{...e,scale:i.payload};case o:return{...e,...i.payload};case"SET_DESIRED_SCROLL_POSITION":return{...e,desiredScrollPosition:i.payload};case n:return{...e,pageChangeState:i.payload};default:return e}},initialState:(t,e)=>((t,e)=>({virtualItems:[],totalPages:t.pages.length,totalContentSize:{width:0,height:0},desiredScrollPosition:{x:0,y:0},strategy:e.strategy??i.Vertical,pageGap:e.pageGap??10,scale:t.scale,pageChangeState:S,...m}))(t,e)};exports.SCROLL_PLUGIN_ID=p,exports.ScrollPlugin=u,exports.ScrollPluginPackage=y,exports.ScrollStrategy=i,exports.manifest=d;
|
|
2
2
|
//# sourceMappingURL=index.cjs.map
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.cjs","sources":["../src/lib/types.ts","../src/lib/strategies/base-strategy.ts","../src/lib/strategies/vertical-strategy.ts","../src/lib/strategies/horizontal-strategy.ts","../src/lib/actions.ts","../src/lib/selectors.ts","../src/lib/scroll-plugin.ts","../src/lib/manifest.ts","../src/lib/reducer.ts","../src/lib/index.ts"],"sourcesContent":["import { BasePluginConfig, Emitter, EventHook } from '@embedpdf/core';\nimport { PdfPageObject, Rect, Rotation } from '@embedpdf/models';\nimport { ViewportMetrics } from '@embedpdf/plugin-viewport';\nimport { VirtualItem } from './types/virtual-item';\n\nexport type ScrollBehavior = 'instant' | 'smooth' | 'auto';\n\nexport interface ScrollState extends ScrollMetrics {\n virtualItems: VirtualItem[];\n totalPages: number;\n totalContentSize: { width: number; height: number };\n desiredScrollPosition: { x: number; y: number };\n strategy: ScrollStrategy;\n pageGap: number;\n scale: number;\n}\n\nexport interface ScrollerLayout {\n startSpacing: number;\n endSpacing: number;\n totalWidth: number;\n totalHeight: number;\n pageGap: number;\n strategy: ScrollState['strategy'];\n items: VirtualItem[];\n}\n\nexport enum ScrollStrategy {\n Vertical = 'vertical',\n Horizontal = 'horizontal',\n}\n\nexport interface PageVisibilityMetrics {\n pageNumber: number;\n viewportX: number;\n viewportY: number;\n visiblePercentage: number;\n original: {\n pageX: number;\n pageY: number;\n visibleWidth: number;\n visibleHeight: number;\n scale: number;\n };\n scaled: {\n pageX: number;\n pageY: number;\n visibleWidth: number;\n visibleHeight: number;\n scale: number;\n };\n}\n\nexport interface ScrollMetrics {\n currentPage: number;\n visiblePages: number[];\n pageVisibilityMetrics: PageVisibilityMetrics[];\n renderedPageIndexes: number[];\n scrollOffset: { x: number; y: number };\n startSpacing: number;\n endSpacing: number;\n}\n\nexport interface ScrollStrategyInterface {\n initialize(container: HTMLElement, innerDiv: HTMLElement): void;\n destroy(): void;\n updateLayout(viewport: ViewportMetrics, pdfPageObject: PdfPageObject[][]): void;\n handleScroll(viewport: ViewportMetrics): void;\n getVirtualItems(): VirtualItem[];\n scrollToPage(pageNumber: number, behavior?: ScrollBehavior): void;\n calculateDimensions(pdfPageObject: PdfPageObject[][]): void;\n}\n\nexport interface ScrollPluginConfig extends BasePluginConfig {\n strategy?: ScrollStrategy;\n initialPage?: number;\n bufferSize?: number;\n pageGap?: number;\n}\n\nexport type LayoutChangePayload = Pick<ScrollState, 'virtualItems' | 'totalContentSize'>;\n\nexport interface ScrollToPageOptions {\n pageNumber: number;\n pageCoordinates?: { x: number; y: number };\n behavior?: ScrollBehavior;\n center?: boolean;\n}\n\nexport interface PageChangePayload {\n pageNumber: number;\n totalPages: number;\n}\n\nexport interface ScrollCapability {\n onStateChange: EventHook<ScrollState>;\n onScroll: EventHook<ScrollMetrics>;\n getCurrentPage(): number;\n getTotalPages(): number;\n onPageChange: EventHook<PageChangePayload>;\n onLayoutChange: EventHook<LayoutChangePayload>;\n onLayoutReady: EventHook<boolean>;\n scrollToPage(options: ScrollToPageOptions): void;\n scrollToNextPage(behavior?: ScrollBehavior): void;\n scrollToPreviousPage(behavior?: ScrollBehavior): void;\n getMetrics(viewport?: ViewportMetrics): ScrollMetrics;\n getLayout(): LayoutChangePayload;\n getRectPositionForPage(\n page: number,\n rect: Rect,\n scale?: number,\n rotation?: Rotation,\n ): Rect | null;\n setScrollStrategy(strategy: ScrollStrategy): void;\n getPageGap(): number;\n}\n","import {\n PdfPageObjectWithRotatedSize,\n Position,\n Rect,\n Rotation,\n scalePosition,\n Size,\n transformPosition,\n transformRect,\n} from '@embedpdf/models';\nimport { ViewportMetrics } from '@embedpdf/plugin-viewport';\nimport { VirtualItem } from '../types/virtual-item';\nimport { ScrollMetrics } from '../types';\n\nexport interface ScrollStrategyConfig {\n pageGap?: number;\n viewportGap?: number;\n bufferSize?: number;\n}\n\nexport abstract class BaseScrollStrategy {\n protected pageGap: number;\n protected viewportGap: number;\n protected bufferSize: number;\n\n constructor(config: ScrollStrategyConfig) {\n this.pageGap = config.pageGap ?? 20;\n this.viewportGap = config.viewportGap ?? 20;\n this.bufferSize = config.bufferSize ?? 2;\n }\n\n abstract createVirtualItems(pdfPageObject: PdfPageObjectWithRotatedSize[][]): VirtualItem[];\n abstract getTotalContentSize(virtualItems: VirtualItem[]): Size;\n protected abstract getScrollOffset(viewport: ViewportMetrics): number;\n protected abstract getClientSize(viewport: ViewportMetrics): number;\n\n protected getVisibleRange(\n viewport: ViewportMetrics,\n virtualItems: VirtualItem[],\n scale: number,\n ): { start: number; end: number } {\n const scrollOffset = this.getScrollOffset(viewport);\n const clientSize = this.getClientSize(viewport);\n const viewportStart = scrollOffset;\n const viewportEnd = scrollOffset + clientSize;\n\n let startIndex = 0;\n while (\n startIndex < virtualItems.length &&\n (virtualItems[startIndex].offset + virtualItems[startIndex].height) * scale <= viewportStart\n ) {\n startIndex++;\n }\n\n let endIndex = startIndex;\n while (endIndex < virtualItems.length && virtualItems[endIndex].offset * scale <= viewportEnd) {\n endIndex++;\n }\n\n return {\n start: Math.max(0, startIndex - this.bufferSize),\n end: Math.min(virtualItems.length - 1, endIndex + this.bufferSize - 1),\n };\n }\n\n handleScroll(\n viewport: ViewportMetrics,\n virtualItems: VirtualItem[],\n scale: number,\n ): ScrollMetrics {\n const range = this.getVisibleRange(viewport, virtualItems, scale);\n const visibleItems = virtualItems.slice(range.start, range.end + 1);\n const pageVisibilityMetrics = this.calculatePageVisibility(visibleItems, viewport, scale);\n const visiblePages = pageVisibilityMetrics.map((m) => m.pageNumber);\n const renderedPageIndexes = virtualItems\n .slice(range.start, range.end + 1)\n .flatMap((item) => item.index);\n const currentPage = this.determineCurrentPage(pageVisibilityMetrics);\n const first = virtualItems[range.start];\n const last = virtualItems[range.end];\n const startSpacing = first ? first.offset * scale : 0;\n const endSpacing = last\n ? (virtualItems[virtualItems.length - 1].offset + // end of content\n virtualItems[virtualItems.length - 1].height) *\n scale - // minus\n (last.offset + last.height) * scale // end of last rendered\n : 0;\n\n return {\n currentPage,\n visiblePages,\n pageVisibilityMetrics,\n renderedPageIndexes,\n scrollOffset: { x: viewport.scrollLeft, y: viewport.scrollTop },\n startSpacing,\n endSpacing,\n };\n }\n\n protected calculatePageVisibility(\n virtualItems: VirtualItem[],\n viewport: ViewportMetrics,\n scale: number,\n ): ScrollMetrics['pageVisibilityMetrics'] {\n const visibilityMetrics: ScrollMetrics['pageVisibilityMetrics'] = [];\n\n virtualItems.forEach((item) => {\n item.pageLayouts.forEach((page) => {\n const itemX = item.x * scale;\n const itemY = item.y * scale;\n const pageX = itemX + page.x * scale;\n const pageY = itemY + page.y * scale;\n const pageWidth = page.rotatedWidth * scale;\n const pageHeight = page.rotatedHeight * scale;\n\n const viewportLeft = viewport.scrollLeft;\n const viewportTop = viewport.scrollTop;\n const viewportRight = viewportLeft + viewport.clientWidth;\n const viewportBottom = viewportTop + viewport.clientHeight;\n\n const intersectionLeft = Math.max(pageX, viewportLeft);\n const intersectionTop = Math.max(pageY, viewportTop);\n const intersectionRight = Math.min(pageX + pageWidth, viewportRight);\n const intersectionBottom = Math.min(pageY + pageHeight, viewportBottom);\n\n if (intersectionLeft < intersectionRight && intersectionTop < intersectionBottom) {\n const visibleWidth = intersectionRight - intersectionLeft;\n const visibleHeight = intersectionBottom - intersectionTop;\n const totalArea = pageWidth * pageHeight;\n const visibleArea = visibleWidth * visibleHeight;\n\n visibilityMetrics.push({\n pageNumber: page.pageNumber,\n viewportX: intersectionLeft - viewportLeft,\n viewportY: intersectionTop - viewportTop,\n visiblePercentage: (visibleArea / totalArea) * 100,\n original: {\n pageX: (intersectionLeft - pageX) / scale,\n pageY: (intersectionTop - pageY) / scale,\n visibleWidth: visibleWidth / scale,\n visibleHeight: visibleHeight / scale,\n scale: 1,\n },\n scaled: {\n pageX: intersectionLeft - pageX,\n pageY: intersectionTop - pageY,\n visibleWidth,\n visibleHeight,\n scale,\n },\n });\n }\n });\n });\n\n return visibilityMetrics;\n }\n\n protected determineCurrentPage(\n visibilityMetrics: ScrollMetrics['pageVisibilityMetrics'],\n ): number {\n if (visibilityMetrics.length === 0) return 1;\n\n const maxVisibility = Math.max(...visibilityMetrics.map((m) => m.visiblePercentage));\n const mostVisiblePages = visibilityMetrics.filter((m) => m.visiblePercentage === maxVisibility);\n\n return mostVisiblePages.length === 1\n ? mostVisiblePages[0].pageNumber\n : mostVisiblePages.sort((a, b) => a.pageNumber - b.pageNumber)[0].pageNumber;\n }\n\n private getRectLocationForPage(\n pageNumber: number,\n virtualItems: VirtualItem[],\n totalContentSize?: Size,\n ): Rect | null {\n // Find the virtual item containing the page\n const item = virtualItems.find((item) => item.pageNumbers.includes(pageNumber));\n if (!item) return null;\n\n // Find the specific page layout for the requested page number\n const pageLayout = item.pageLayouts.find((layout) => layout.pageNumber === pageNumber);\n if (!pageLayout) return null;\n\n // Calculate centering offset for items that are narrower than the maximum width\n let centeringOffsetX = 0;\n if (totalContentSize) {\n const maxWidth = totalContentSize.width;\n if (item.width < maxWidth) {\n centeringOffsetX = (maxWidth - item.width) / 2;\n }\n }\n\n return {\n origin: {\n x: item.x + pageLayout.x + centeringOffsetX,\n y: item.y + pageLayout.y,\n },\n size: {\n width: pageLayout.width,\n height: pageLayout.height,\n },\n };\n }\n\n getScrollPositionForPage(\n pageNumber: number,\n virtualItems: VirtualItem[],\n scale: number,\n rotation: Rotation,\n pageCoordinates?: { x: number; y: number },\n ): Position | null {\n const totalContentSize = this.getTotalContentSize(virtualItems);\n const pageRect = this.getRectLocationForPage(pageNumber, virtualItems, totalContentSize);\n if (!pageRect) return null;\n\n const scaledBasePosition = scalePosition(pageRect.origin, scale);\n\n // If specific page coordinates are provided, add them to the base position\n if (pageCoordinates) {\n const rotatedSize = transformPosition(\n {\n width: pageRect.size.width,\n height: pageRect.size.height,\n },\n {\n x: pageCoordinates.x,\n y: pageCoordinates.y,\n },\n rotation,\n scale,\n );\n\n return {\n x: scaledBasePosition.x + rotatedSize.x + this.viewportGap,\n y: scaledBasePosition.y + rotatedSize.y + this.viewportGap,\n };\n }\n\n return {\n x: scaledBasePosition.x + this.viewportGap,\n y: scaledBasePosition.y + this.viewportGap,\n };\n }\n\n getRectPositionForPage(\n pageNumber: number,\n virtualItems: VirtualItem[],\n scale: number,\n rotation: Rotation,\n rect: Rect,\n ): Rect | null {\n const totalContentSize = this.getTotalContentSize(virtualItems);\n const pageRect = this.getRectLocationForPage(pageNumber, virtualItems, totalContentSize);\n if (!pageRect) return null;\n\n const scaledBasePosition = scalePosition(pageRect.origin, scale);\n\n const rotatedSize = transformRect(\n {\n width: pageRect.size.width,\n height: pageRect.size.height,\n },\n rect,\n rotation,\n scale,\n );\n\n return {\n origin: {\n x: scaledBasePosition.x + rotatedSize.origin.x,\n y: scaledBasePosition.y + rotatedSize.origin.y,\n },\n size: rotatedSize.size,\n };\n }\n}\n","import { PdfPageObjectWithRotatedSize } from '@embedpdf/models';\nimport { ViewportMetrics } from '@embedpdf/plugin-viewport';\nimport { BaseScrollStrategy, ScrollStrategyConfig } from './base-strategy';\nimport { VirtualItem, PageLayout } from '../types/virtual-item';\nimport { ScrollMetrics } from '../types';\n\nexport class VerticalScrollStrategy extends BaseScrollStrategy {\n constructor(config: ScrollStrategyConfig) {\n super(config);\n }\n\n createVirtualItems(pdfPageObject: PdfPageObjectWithRotatedSize[][]): VirtualItem[] {\n let yOffset = 0;\n return pdfPageObject.map((pagesInSpread, index) => {\n let pageX = 0;\n const pageLayouts: PageLayout[] = pagesInSpread.map((page) => {\n const layout: PageLayout = {\n pageNumber: page.index + 1,\n pageIndex: page.index,\n x: pageX,\n y: 0,\n width: page.size.width,\n height: page.size.height,\n rotatedWidth: page.rotatedSize.width,\n rotatedHeight: page.rotatedSize.height,\n };\n pageX += page.rotatedSize.width + this.pageGap;\n return layout;\n });\n const width = pagesInSpread.reduce(\n (sum, page, i) =>\n sum + page.rotatedSize.width + (i < pagesInSpread.length - 1 ? this.pageGap : 0),\n 0,\n );\n const height = Math.max(...pagesInSpread.map((p) => p.rotatedSize.height));\n const item: VirtualItem = {\n id: `item-${index}`,\n x: 0,\n y: yOffset,\n offset: yOffset,\n width,\n height,\n pageLayouts,\n pageNumbers: pagesInSpread.map((p) => p.index + 1),\n index,\n };\n yOffset += height + this.pageGap;\n return item;\n });\n }\n\n getTotalContentSize(virtualItems: VirtualItem[]): { width: number; height: number } {\n if (virtualItems.length === 0) return { width: 0, height: 0 };\n const maxWidth = Math.max(...virtualItems.map((item) => item.width));\n const totalHeight =\n virtualItems[virtualItems.length - 1].y + virtualItems[virtualItems.length - 1].height;\n return {\n width: maxWidth,\n height: totalHeight,\n };\n }\n\n protected getScrollOffset(viewport: ViewportMetrics): number {\n return viewport.scrollTop;\n }\n\n protected getClientSize(viewport: ViewportMetrics): number {\n return viewport.clientHeight;\n }\n}\n","import { PdfPageObjectWithRotatedSize } from '@embedpdf/models';\nimport { ViewportMetrics } from '@embedpdf/plugin-viewport';\nimport { BaseScrollStrategy, ScrollStrategyConfig } from './base-strategy';\nimport { VirtualItem, PageLayout } from '../types/virtual-item';\n\nexport class HorizontalScrollStrategy extends BaseScrollStrategy {\n constructor(config: ScrollStrategyConfig) {\n super(config);\n }\n\n createVirtualItems(pdfPageObject: PdfPageObjectWithRotatedSize[][]): VirtualItem[] {\n let xOffset = 0;\n return pdfPageObject.map((pagesInSpread, index) => {\n let pageX = 0;\n const pageLayouts: PageLayout[] = pagesInSpread.map((page) => {\n const layout: PageLayout = {\n pageNumber: page.index + 1,\n pageIndex: page.index,\n x: pageX,\n y: 0,\n width: page.size.width,\n height: page.size.height,\n rotatedWidth: page.rotatedSize.width,\n rotatedHeight: page.rotatedSize.height,\n };\n pageX += page.rotatedSize.width + this.pageGap;\n return layout;\n });\n const width = pagesInSpread.reduce(\n (sum, page, i) =>\n sum + page.rotatedSize.width + (i < pagesInSpread.length - 1 ? this.pageGap : 0),\n 0,\n );\n const height = Math.max(...pagesInSpread.map((p) => p.rotatedSize.height));\n const item: VirtualItem = {\n id: `item-${index}`,\n x: xOffset,\n y: 0,\n offset: xOffset,\n width,\n height,\n pageLayouts,\n pageNumbers: pagesInSpread.map((p) => p.index + 1),\n index,\n };\n xOffset += width + this.pageGap;\n return item;\n });\n }\n\n getTotalContentSize(virtualItems: VirtualItem[]): { width: number; height: number } {\n if (virtualItems.length === 0) return { width: 0, height: 0 };\n const totalWidth =\n virtualItems[virtualItems.length - 1].x + virtualItems[virtualItems.length - 1].width;\n const maxHeight = Math.max(...virtualItems.map((item) => item.height));\n return {\n width: totalWidth,\n height: maxHeight,\n };\n }\n\n protected getScrollOffset(viewport: ViewportMetrics): number {\n return viewport.scrollLeft;\n }\n\n protected getClientSize(viewport: ViewportMetrics): number {\n return viewport.clientWidth;\n }\n}\n","import { Action } from '@embedpdf/core';\nimport { ScrollState } from './types';\n\nexport const UPDATE_SCROLL_STATE = 'UPDATE_SCROLL_STATE';\nexport const SET_DESIRED_SCROLL_POSITION = 'SET_DESIRED_SCROLL_POSITION';\nexport const UPDATE_TOTAL_PAGES = 'UPDATE_TOTAL_PAGES';\n\nexport interface UpdateScrollStateAction extends Action {\n type: typeof UPDATE_SCROLL_STATE;\n payload: Partial<ScrollState>;\n}\n\nexport interface SetDesiredScrollPositionAction extends Action {\n type: typeof SET_DESIRED_SCROLL_POSITION;\n payload: { x: number; y: number };\n}\n\nexport interface UpdateTotalPagesAction extends Action {\n type: typeof UPDATE_TOTAL_PAGES;\n payload: number;\n}\n\nexport type ScrollAction =\n | UpdateScrollStateAction\n | SetDesiredScrollPositionAction\n | UpdateTotalPagesAction;\n\nexport function updateScrollState(payload: Partial<ScrollState>): UpdateScrollStateAction {\n return { type: UPDATE_SCROLL_STATE, payload };\n}\n\nexport function setDesiredScrollPosition(payload: {\n x: number;\n y: number;\n}): SetDesiredScrollPositionAction {\n return { type: SET_DESIRED_SCROLL_POSITION, payload };\n}\n\nexport function updateTotalPages(payload: number): UpdateTotalPagesAction {\n return { type: UPDATE_TOTAL_PAGES, payload };\n}\n","import { ScrollerLayout, ScrollState } from './types';\n\nexport const getScrollerLayout = (state: ScrollState, scale: number): ScrollerLayout => {\n return {\n startSpacing: state.startSpacing,\n endSpacing: state.endSpacing,\n totalWidth: state.totalContentSize.width * scale,\n totalHeight: state.totalContentSize.height * scale,\n pageGap: state.pageGap * scale,\n strategy: state.strategy,\n items: state.renderedPageIndexes.map((idx) => {\n return {\n ...state.virtualItems[idx],\n pageLayouts: state.virtualItems[idx].pageLayouts.map((layout) => {\n return {\n ...layout,\n rotatedWidth: layout.rotatedWidth * scale,\n rotatedHeight: layout.rotatedHeight * scale,\n width: layout.width * scale,\n height: layout.height * scale,\n };\n }),\n };\n }),\n };\n};\n","import {\n BasePlugin,\n CoreState,\n PluginRegistry,\n SET_DOCUMENT,\n SET_PAGES,\n SET_ROTATION,\n StoreState,\n Unsubscribe,\n createBehaviorEmitter,\n getPagesWithRotatedSize,\n} from '@embedpdf/core';\nimport { PdfPageObjectWithRotatedSize, Rect, Rotation } from '@embedpdf/models';\nimport { ViewportCapability, ViewportMetrics, ViewportPlugin } from '@embedpdf/plugin-viewport';\nimport {\n ScrollCapability,\n ScrollPluginConfig,\n ScrollStrategy,\n ScrollMetrics,\n ScrollState,\n LayoutChangePayload,\n ScrollerLayout,\n ScrollToPageOptions,\n PageChangePayload,\n ScrollBehavior,\n} from './types';\nimport { BaseScrollStrategy, ScrollStrategyConfig } from './strategies/base-strategy';\nimport { VerticalScrollStrategy } from './strategies/vertical-strategy';\nimport { HorizontalScrollStrategy } from './strategies/horizontal-strategy';\nimport { updateScrollState, ScrollAction, updateTotalPages } from './actions';\nimport { VirtualItem } from './types/virtual-item';\nimport { getScrollerLayout } from './selectors';\n\ntype PartialScroll = Partial<ScrollState>;\ntype Emits = {\n layout?: LayoutChangePayload;\n metrics?: ScrollMetrics;\n};\n\nexport class ScrollPlugin extends BasePlugin<\n ScrollPluginConfig,\n ScrollCapability,\n ScrollState,\n ScrollAction\n> {\n static readonly id = 'scroll' as const;\n private viewport: ViewportCapability;\n private strategy: BaseScrollStrategy;\n private strategyConfig: ScrollStrategyConfig;\n private currentScale: number = 1;\n private currentRotation: Rotation = Rotation.Degree0;\n private initialPage?: number;\n private currentPage: number = 1;\n private layoutReady: boolean = false;\n\n private readonly layout$ = createBehaviorEmitter<LayoutChangePayload>();\n private readonly scroll$ = createBehaviorEmitter<ScrollMetrics>();\n private readonly state$ = createBehaviorEmitter<ScrollState>();\n private readonly scrollerLayout$ = createBehaviorEmitter<ScrollerLayout>();\n private readonly pageChange$ = createBehaviorEmitter<PageChangePayload>();\n private readonly layoutReady$ = createBehaviorEmitter<boolean>();\n\n constructor(\n public readonly id: string,\n registry: PluginRegistry,\n private config?: ScrollPluginConfig,\n ) {\n super(id, registry);\n\n this.viewport = this.registry.getPlugin<ViewportPlugin>('viewport')!.provides();\n\n this.strategyConfig = {\n pageGap: this.config?.pageGap ?? 10,\n viewportGap: this.viewport.getViewportGap(),\n bufferSize: this.config?.bufferSize ?? 2,\n };\n\n this.strategy =\n this.config?.strategy === ScrollStrategy.Horizontal\n ? new HorizontalScrollStrategy(this.strategyConfig)\n : new VerticalScrollStrategy(this.strategyConfig);\n\n this.initialPage = this.config?.initialPage;\n this.currentScale = this.coreState.core.scale;\n this.currentRotation = this.coreState.core.rotation;\n // Subscribe to viewport and page manager events\n this.viewport.onViewportChange((vp) => this.commitMetrics(this.computeMetrics(vp)), {\n mode: 'throttle',\n wait: 100,\n });\n this.coreStore.onAction(SET_DOCUMENT, (_action, state) => {\n const totalPages = state.core.pages.length;\n this.dispatch(updateTotalPages(totalPages));\n this.pageChange$.emit({ pageNumber: this.currentPage, totalPages });\n this.refreshAll(getPagesWithRotatedSize(state.core), this.viewport.getMetrics());\n });\n this.coreStore.onAction(SET_ROTATION, (_action, state) =>\n this.refreshAll(getPagesWithRotatedSize(state.core), this.viewport.getMetrics()),\n );\n this.coreStore.onAction(SET_PAGES, (_action, state) =>\n this.refreshAll(getPagesWithRotatedSize(state.core), this.viewport.getMetrics()),\n );\n }\n\n /* ------------------------------------------------------------------ */\n /* ᴄᴏᴍᴘᴜᴛᴇʀs */\n /* ------------------------------------------------------------------ */\n\n private computeLayout(pages: PdfPageObjectWithRotatedSize[][]) {\n const virtualItems = this.strategy.createVirtualItems(pages);\n const totalContentSize = this.strategy.getTotalContentSize(virtualItems);\n return { virtualItems, totalContentSize };\n }\n\n private computeMetrics(vp: ViewportMetrics, items: VirtualItem[] = this.state.virtualItems) {\n return this.strategy.handleScroll(vp, items, this.currentScale);\n }\n\n /* ------------------------------------------------------------------ */\n /* ᴄᴏᴍᴍɪᴛ (single source of truth) */\n /* ------------------------------------------------------------------ */\n\n private commit(stateDelta: PartialScroll, emit?: Emits) {\n /* update Redux-like store */\n this.dispatch(updateScrollState(stateDelta));\n\n /* fire optional events */\n if (emit?.layout) this.layout$.emit(emit.layout);\n if (emit?.metrics) {\n this.scroll$.emit(emit.metrics);\n\n if (emit.metrics.currentPage !== this.currentPage) {\n this.currentPage = emit.metrics.currentPage;\n this.pageChange$.emit({ pageNumber: this.currentPage, totalPages: this.state.totalPages });\n }\n }\n\n /* keep scroller-layout reactive */\n this.scrollerLayout$.emit(this.getScrollerLayout());\n }\n\n /* convenience wrappers */\n private commitMetrics(metrics: ScrollMetrics) {\n this.commit(metrics, { metrics });\n }\n\n /* full re-compute after page-spread or initialisation */\n private refreshAll(pages: PdfPageObjectWithRotatedSize[][], vp: ViewportMetrics) {\n const layout = this.computeLayout(pages);\n const metrics = this.computeMetrics(vp, layout.virtualItems);\n\n this.commit({ ...layout, ...metrics }, { layout, metrics });\n }\n\n private getVirtualItemsFromState(): VirtualItem[] {\n return this.state.virtualItems || [];\n }\n\n public onScrollerData(callback: (layout: ScrollerLayout) => void): Unsubscribe {\n return this.scrollerLayout$.on(callback);\n }\n\n public getScrollerLayout(): ScrollerLayout {\n const scale = this.coreState.core.scale;\n return getScrollerLayout(this.state, scale);\n }\n\n private pushScrollLayout() {\n this.scrollerLayout$.emit(this.getScrollerLayout());\n }\n\n override onStoreUpdated(_prevState: ScrollState, _newState: ScrollState): void {\n this.pushScrollLayout();\n }\n\n override onCoreStoreUpdated(\n prevState: StoreState<CoreState>,\n newState: StoreState<CoreState>,\n ): void {\n if (prevState.core.scale !== newState.core.scale) {\n this.currentScale = newState.core.scale;\n this.commitMetrics(this.computeMetrics(this.viewport.getMetrics()));\n }\n if (prevState.core.rotation !== newState.core.rotation) {\n this.currentRotation = newState.core.rotation;\n }\n }\n\n /**\n * Change the scroll strategy at runtime (e.g., vertical <-> horizontal)\n * @param newStrategy ScrollStrategy.Horizontal or ScrollStrategy.Vertical\n */\n private setScrollStrategy(newStrategy: ScrollStrategy) {\n // Only update if the strategy is actually changing\n if (\n (newStrategy === ScrollStrategy.Horizontal &&\n this.strategy instanceof HorizontalScrollStrategy) ||\n (newStrategy === ScrollStrategy.Vertical && this.strategy instanceof VerticalScrollStrategy)\n ) {\n return;\n }\n\n this.strategy =\n newStrategy === ScrollStrategy.Horizontal\n ? new HorizontalScrollStrategy(this.strategyConfig)\n : new VerticalScrollStrategy(this.strategyConfig);\n\n // Update state with new strategy\n this.dispatch(\n updateScrollState({\n strategy: newStrategy,\n }),\n );\n\n // Recalculate layout and scroll metrics\n const pages = getPagesWithRotatedSize(this.coreState.core);\n this.refreshAll(pages, this.viewport.getMetrics());\n }\n\n public setLayoutReady() {\n if (this.layoutReady) return;\n\n this.layoutReady = true;\n this.layoutReady$.emit(true);\n\n if (this.initialPage) {\n this.scrollToPage({ pageNumber: this.initialPage, behavior: 'instant' });\n }\n }\n\n protected buildCapability(): ScrollCapability {\n return {\n onStateChange: this.state$.on,\n onLayoutChange: this.layout$.on,\n onScroll: this.scroll$.on,\n onPageChange: this.pageChange$.on,\n onLayoutReady: this.layoutReady$.on,\n getCurrentPage: () => this.currentPage,\n getTotalPages: () => this.state.totalPages,\n scrollToPage: this.scrollToPage.bind(this),\n scrollToNextPage: this.scrollToNextPage.bind(this),\n scrollToPreviousPage: this.scrollToPreviousPage.bind(this),\n getMetrics: this.getMetrics.bind(this),\n getLayout: this.getLayout.bind(this),\n getRectPositionForPage: this.getRectPositionForPage.bind(this),\n getPageGap: () => this.state.pageGap,\n setScrollStrategy: (strategy: ScrollStrategy) => this.setScrollStrategy(strategy),\n };\n }\n\n private scrollToPage(options: ScrollToPageOptions) {\n const { pageNumber, behavior = 'smooth', pageCoordinates, center = false } = options;\n const virtualItems = this.getVirtualItemsFromState();\n const position = this.strategy.getScrollPositionForPage(\n pageNumber,\n virtualItems,\n this.currentScale,\n this.currentRotation,\n pageCoordinates,\n );\n if (position) {\n this.viewport.scrollTo({ ...position, behavior, center });\n }\n }\n\n private scrollToNextPage(behavior: ScrollBehavior = 'smooth') {\n const virtualItems = this.getVirtualItemsFromState();\n const currentItemIndex = virtualItems.findIndex((item) =>\n item.pageNumbers.includes(this.currentPage),\n );\n if (currentItemIndex >= 0 && currentItemIndex < virtualItems.length - 1) {\n const nextItem = virtualItems[currentItemIndex + 1];\n const position = this.strategy.getScrollPositionForPage(\n nextItem.pageNumbers[0],\n virtualItems,\n this.currentScale,\n this.currentRotation,\n );\n if (position) {\n this.viewport.scrollTo({ ...position, behavior });\n }\n }\n }\n\n private scrollToPreviousPage(behavior: ScrollBehavior = 'smooth') {\n const virtualItems = this.getVirtualItemsFromState();\n const currentItemIndex = virtualItems.findIndex((item) =>\n item.pageNumbers.includes(this.currentPage),\n );\n if (currentItemIndex > 0) {\n const prevItem = virtualItems[currentItemIndex - 1];\n const position = this.strategy.getScrollPositionForPage(\n prevItem.pageNumbers[0],\n virtualItems,\n this.currentScale,\n this.currentRotation,\n );\n if (position) {\n this.viewport.scrollTo({ ...position, behavior });\n }\n }\n }\n\n private getMetrics(viewport?: ViewportMetrics): ScrollMetrics {\n const metrics = viewport || this.viewport.getMetrics();\n const virtualItems = this.getVirtualItemsFromState();\n return this.strategy.handleScroll(metrics, virtualItems, this.currentScale);\n }\n\n private getLayout(): LayoutChangePayload {\n return {\n virtualItems: this.state.virtualItems,\n totalContentSize: this.state.totalContentSize,\n };\n }\n\n private getRectPositionForPage(\n pageIndex: number,\n rect: Rect,\n scale?: number,\n rotation?: Rotation,\n ): Rect | null {\n return this.strategy.getRectPositionForPage(\n pageIndex + 1,\n this.state.virtualItems,\n scale ?? this.currentScale,\n rotation ?? this.currentRotation,\n rect,\n );\n }\n\n async initialize(): Promise<void> {\n // No DOM initialization needed; state drives rendering\n }\n\n async destroy(): Promise<void> {\n this.layout$.clear();\n this.scroll$.clear();\n this.pageChange$.clear();\n this.state$.clear();\n this.scrollerLayout$.clear();\n this.layoutReady$.clear();\n super.destroy();\n }\n}\n","import { PluginManifest } from '@embedpdf/core';\nimport { ScrollPluginConfig } from './types';\n\nexport const SCROLL_PLUGIN_ID = 'scroll';\n\nexport const manifest: PluginManifest<ScrollPluginConfig> = {\n id: SCROLL_PLUGIN_ID,\n name: 'Scroll Plugin',\n version: '1.0.0',\n provides: ['scroll'],\n requires: ['viewport'],\n optional: [],\n defaultConfig: {\n enabled: true,\n pageGap: 10,\n },\n};\n","import { Reducer, CoreState, SET_SCALE, SetScaleAction } from '@embedpdf/core';\nimport { ScrollState, ScrollStrategy, ScrollPluginConfig, ScrollMetrics } from './types';\nimport {\n ScrollAction,\n UPDATE_SCROLL_STATE,\n SET_DESIRED_SCROLL_POSITION,\n UPDATE_TOTAL_PAGES,\n} from './actions';\n\nexport const defaultScrollMetrics: ScrollMetrics = {\n currentPage: 1,\n visiblePages: [],\n pageVisibilityMetrics: [],\n renderedPageIndexes: [],\n scrollOffset: { x: 0, y: 0 },\n startSpacing: 0,\n endSpacing: 0,\n};\n\nexport const initialState: (coreState: CoreState, config: ScrollPluginConfig) => ScrollState = (\n coreState,\n config,\n) => ({\n virtualItems: [],\n totalPages: coreState.pages.length,\n totalContentSize: { width: 0, height: 0 },\n desiredScrollPosition: { x: 0, y: 0 },\n strategy: config.strategy ?? ScrollStrategy.Vertical,\n pageGap: config.pageGap ?? 10,\n scale: coreState.scale,\n ...defaultScrollMetrics,\n});\n\nexport const scrollReducer: Reducer<ScrollState, ScrollAction | SetScaleAction> = (\n state,\n action,\n) => {\n switch (action.type) {\n case UPDATE_TOTAL_PAGES:\n return { ...state, totalPages: action.payload };\n case SET_SCALE:\n return { ...state, scale: action.payload };\n case UPDATE_SCROLL_STATE:\n return { ...state, ...action.payload };\n case SET_DESIRED_SCROLL_POSITION:\n return { ...state, desiredScrollPosition: action.payload };\n default:\n return state;\n }\n};\n","import { PluginPackage } from '@embedpdf/core';\nimport { ScrollPlugin } from './scroll-plugin';\nimport { manifest, SCROLL_PLUGIN_ID } from './manifest';\nimport { ScrollPluginConfig, ScrollState } from './types';\nimport { scrollReducer, initialState } from './reducer';\nimport { ScrollAction } from './actions';\n\nexport const ScrollPluginPackage: PluginPackage<\n ScrollPlugin,\n ScrollPluginConfig,\n ScrollState,\n ScrollAction\n> = {\n manifest,\n create: (registry, config) => new ScrollPlugin(SCROLL_PLUGIN_ID, registry, config),\n reducer: scrollReducer,\n initialState: (coreState, config) => initialState(coreState, config),\n};\n\nexport * from './scroll-plugin';\nexport * from './types';\nexport * from './manifest';\nexport * from './types/virtual-item';\n"],"names":["ScrollStrategy","BaseScrollStrategy","constructor","config","this","pageGap","viewportGap","bufferSize","getVisibleRange","viewport","virtualItems","scale","scrollOffset","getScrollOffset","viewportStart","viewportEnd","getClientSize","startIndex","length","offset","height","endIndex","start","Math","max","end","min","handleScroll","range","visibleItems","slice","pageVisibilityMetrics","calculatePageVisibility","visiblePages","map","m","pageNumber","renderedPageIndexes","flatMap","item","index","currentPage","determineCurrentPage","first","last","startSpacing","endSpacing","x","scrollLeft","y","scrollTop","visibilityMetrics","forEach","pageLayouts","page","itemX","itemY","pageX","pageY","pageWidth","rotatedWidth","pageHeight","rotatedHeight","viewportLeft","viewportTop","viewportRight","clientWidth","viewportBottom","clientHeight","intersectionLeft","intersectionTop","intersectionRight","intersectionBottom","visibleWidth","visibleHeight","totalArea","visibleArea","push","viewportX","viewportY","visiblePercentage","original","scaled","maxVisibility","mostVisiblePages","filter","sort","a","b","getRectLocationForPage","totalContentSize","find","pageNumbers","includes","pageLayout","layout","centeringOffsetX","maxWidth","width","origin","size","getScrollPositionForPage","rotation","pageCoordinates","getTotalContentSize","pageRect","scaledBasePosition","scalePosition","rotatedSize","transformPosition","getRectPositionForPage","rect","transformRect","VerticalScrollStrategy","super","createVirtualItems","pdfPageObject","yOffset","pagesInSpread","pageIndex","reduce","sum","i","p","id","HorizontalScrollStrategy","xOffset","UPDATE_SCROLL_STATE","UPDATE_TOTAL_PAGES","updateScrollState","payload","type","_ScrollPlugin","BasePlugin","registry","currentScale","currentRotation","Rotation","Degree0","layoutReady","layout$","createBehaviorEmitter","scroll$","state$","scrollerLayout$","pageChange$","layoutReady$","getPlugin","provides","strategyConfig","_a","getViewportGap","_b","strategy","_c","Horizontal","initialPage","_d","coreState","core","onViewportChange","vp","commitMetrics","computeMetrics","mode","wait","coreStore","onAction","SET_DOCUMENT","_action","state","totalPages","pages","dispatch","emit","refreshAll","getPagesWithRotatedSize","getMetrics","SET_ROTATION","SET_PAGES","computeLayout","items","commit","stateDelta","metrics","getScrollerLayout","getVirtualItemsFromState","onScrollerData","callback","on","totalWidth","totalHeight","idx","pushScrollLayout","onStoreUpdated","_prevState","_newState","onCoreStoreUpdated","prevState","newState","setScrollStrategy","newStrategy","Vertical","setLayoutReady","scrollToPage","behavior","buildCapability","onStateChange","onLayoutChange","onScroll","onPageChange","onLayoutReady","getCurrentPage","getTotalPages","bind","scrollToNextPage","scrollToPreviousPage","getLayout","getPageGap","options","center","position","scrollTo","currentItemIndex","findIndex","nextItem","prevItem","initialize","destroy","clear","ScrollPlugin","SCROLL_PLUGIN_ID","manifest","name","version","requires","optional","defaultConfig","enabled","defaultScrollMetrics","ScrollPluginPackage","create","reducer","action","SET_SCALE","desiredScrollPosition","initialState"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.cjs","sources":["../src/lib/types.ts","../src/lib/strategies/base-strategy.ts","../src/lib/strategies/vertical-strategy.ts","../src/lib/strategies/horizontal-strategy.ts","../src/lib/actions.ts","../src/lib/selectors.ts","../src/lib/scroll-plugin.ts","../src/lib/manifest.ts","../src/lib/reducer.ts","../src/lib/index.ts"],"sourcesContent":["import { BasePluginConfig, Emitter, EventHook } from '@embedpdf/core';\nimport { PdfPageObject, Rect, Rotation } from '@embedpdf/models';\nimport { ViewportMetrics } from '@embedpdf/plugin-viewport';\nimport { VirtualItem } from './types/virtual-item';\n\nexport type ScrollBehavior = 'instant' | 'smooth' | 'auto';\n\nexport interface PageChangeState {\n isChanging: boolean;\n targetPage: number;\n fromPage: number;\n startTime: number;\n}\n\nexport interface ScrollState extends ScrollMetrics {\n virtualItems: VirtualItem[];\n totalPages: number;\n totalContentSize: { width: number; height: number };\n desiredScrollPosition: { x: number; y: number };\n strategy: ScrollStrategy;\n pageGap: number;\n scale: number;\n pageChangeState: PageChangeState;\n}\n\nexport interface ScrollerLayout {\n startSpacing: number;\n endSpacing: number;\n totalWidth: number;\n totalHeight: number;\n pageGap: number;\n strategy: ScrollState['strategy'];\n items: VirtualItem[];\n}\n\nexport enum ScrollStrategy {\n Vertical = 'vertical',\n Horizontal = 'horizontal',\n}\n\nexport interface PageVisibilityMetrics {\n pageNumber: number;\n viewportX: number;\n viewportY: number;\n visiblePercentage: number;\n original: {\n pageX: number;\n pageY: number;\n visibleWidth: number;\n visibleHeight: number;\n scale: number;\n };\n scaled: {\n pageX: number;\n pageY: number;\n visibleWidth: number;\n visibleHeight: number;\n scale: number;\n };\n}\n\nexport interface ScrollMetrics {\n currentPage: number;\n visiblePages: number[];\n pageVisibilityMetrics: PageVisibilityMetrics[];\n renderedPageIndexes: number[];\n scrollOffset: { x: number; y: number };\n startSpacing: number;\n endSpacing: number;\n}\n\nexport interface ScrollStrategyInterface {\n initialize(container: HTMLElement, innerDiv: HTMLElement): void;\n destroy(): void;\n updateLayout(viewport: ViewportMetrics, pdfPageObject: PdfPageObject[][]): void;\n handleScroll(viewport: ViewportMetrics): void;\n getVirtualItems(): VirtualItem[];\n scrollToPage(pageNumber: number, behavior?: ScrollBehavior): void;\n calculateDimensions(pdfPageObject: PdfPageObject[][]): void;\n}\n\nexport interface ScrollPluginConfig extends BasePluginConfig {\n strategy?: ScrollStrategy;\n initialPage?: number;\n bufferSize?: number;\n pageGap?: number;\n}\n\nexport type LayoutChangePayload = Pick<ScrollState, 'virtualItems' | 'totalContentSize'>;\n\nexport interface ScrollToPageOptions {\n pageNumber: number;\n pageCoordinates?: { x: number; y: number };\n behavior?: ScrollBehavior;\n center?: boolean;\n}\n\nexport interface PageChangePayload {\n pageNumber: number;\n totalPages: number;\n}\n\nexport interface ScrollCapability {\n onStateChange: EventHook<ScrollState>;\n onScroll: EventHook<ScrollMetrics>;\n getCurrentPage(): number;\n getTotalPages(): number;\n getPageChangeState(): PageChangeState;\n onPageChange: EventHook<PageChangePayload>;\n onLayoutChange: EventHook<LayoutChangePayload>;\n onPageChangeState: EventHook<PageChangeState>;\n onLayoutReady: EventHook<boolean>;\n scrollToPage(options: ScrollToPageOptions): void;\n scrollToNextPage(behavior?: ScrollBehavior): void;\n scrollToPreviousPage(behavior?: ScrollBehavior): void;\n getMetrics(viewport?: ViewportMetrics): ScrollMetrics;\n getLayout(): LayoutChangePayload;\n getRectPositionForPage(\n page: number,\n rect: Rect,\n scale?: number,\n rotation?: Rotation,\n ): Rect | null;\n setScrollStrategy(strategy: ScrollStrategy): void;\n getPageGap(): number;\n getPageChangeState: () => PageChangeState;\n}\n","import {\n PdfPageObjectWithRotatedSize,\n Position,\n Rect,\n Rotation,\n scalePosition,\n Size,\n transformPosition,\n transformRect,\n} from '@embedpdf/models';\nimport { ViewportMetrics } from '@embedpdf/plugin-viewport';\nimport { VirtualItem } from '../types/virtual-item';\nimport { ScrollMetrics } from '../types';\n\nexport interface ScrollStrategyConfig {\n pageGap?: number;\n viewportGap?: number;\n bufferSize?: number;\n}\n\nexport abstract class BaseScrollStrategy {\n protected pageGap: number;\n protected viewportGap: number;\n protected bufferSize: number;\n\n constructor(config: ScrollStrategyConfig) {\n this.pageGap = config.pageGap ?? 20;\n this.viewportGap = config.viewportGap ?? 20;\n this.bufferSize = config.bufferSize ?? 2;\n }\n\n abstract createVirtualItems(pdfPageObject: PdfPageObjectWithRotatedSize[][]): VirtualItem[];\n abstract getTotalContentSize(virtualItems: VirtualItem[]): Size;\n protected abstract getScrollOffset(viewport: ViewportMetrics): number;\n protected abstract getClientSize(viewport: ViewportMetrics): number;\n\n protected getVisibleRange(\n viewport: ViewportMetrics,\n virtualItems: VirtualItem[],\n scale: number,\n ): { start: number; end: number } {\n const scrollOffset = this.getScrollOffset(viewport);\n const clientSize = this.getClientSize(viewport);\n const viewportStart = scrollOffset;\n const viewportEnd = scrollOffset + clientSize;\n\n let startIndex = 0;\n while (\n startIndex < virtualItems.length &&\n (virtualItems[startIndex].offset + virtualItems[startIndex].height) * scale <= viewportStart\n ) {\n startIndex++;\n }\n\n let endIndex = startIndex;\n while (endIndex < virtualItems.length && virtualItems[endIndex].offset * scale <= viewportEnd) {\n endIndex++;\n }\n\n return {\n start: Math.max(0, startIndex - this.bufferSize),\n end: Math.min(virtualItems.length - 1, endIndex + this.bufferSize - 1),\n };\n }\n\n handleScroll(\n viewport: ViewportMetrics,\n virtualItems: VirtualItem[],\n scale: number,\n ): ScrollMetrics {\n const range = this.getVisibleRange(viewport, virtualItems, scale);\n const visibleItems = virtualItems.slice(range.start, range.end + 1);\n const pageVisibilityMetrics = this.calculatePageVisibility(visibleItems, viewport, scale);\n const visiblePages = pageVisibilityMetrics.map((m) => m.pageNumber);\n const renderedPageIndexes = virtualItems\n .slice(range.start, range.end + 1)\n .flatMap((item) => item.index);\n const currentPage = this.determineCurrentPage(pageVisibilityMetrics);\n const first = virtualItems[range.start];\n const last = virtualItems[range.end];\n const startSpacing = first ? first.offset * scale : 0;\n const endSpacing = last\n ? (virtualItems[virtualItems.length - 1].offset + // end of content\n virtualItems[virtualItems.length - 1].height) *\n scale - // minus\n (last.offset + last.height) * scale // end of last rendered\n : 0;\n\n return {\n currentPage,\n visiblePages,\n pageVisibilityMetrics,\n renderedPageIndexes,\n scrollOffset: { x: viewport.scrollLeft, y: viewport.scrollTop },\n startSpacing,\n endSpacing,\n };\n }\n\n protected calculatePageVisibility(\n virtualItems: VirtualItem[],\n viewport: ViewportMetrics,\n scale: number,\n ): ScrollMetrics['pageVisibilityMetrics'] {\n const visibilityMetrics: ScrollMetrics['pageVisibilityMetrics'] = [];\n\n virtualItems.forEach((item) => {\n item.pageLayouts.forEach((page) => {\n const itemX = item.x * scale;\n const itemY = item.y * scale;\n const pageX = itemX + page.x * scale;\n const pageY = itemY + page.y * scale;\n const pageWidth = page.rotatedWidth * scale;\n const pageHeight = page.rotatedHeight * scale;\n\n const viewportLeft = viewport.scrollLeft;\n const viewportTop = viewport.scrollTop;\n const viewportRight = viewportLeft + viewport.clientWidth;\n const viewportBottom = viewportTop + viewport.clientHeight;\n\n const intersectionLeft = Math.max(pageX, viewportLeft);\n const intersectionTop = Math.max(pageY, viewportTop);\n const intersectionRight = Math.min(pageX + pageWidth, viewportRight);\n const intersectionBottom = Math.min(pageY + pageHeight, viewportBottom);\n\n if (intersectionLeft < intersectionRight && intersectionTop < intersectionBottom) {\n const visibleWidth = intersectionRight - intersectionLeft;\n const visibleHeight = intersectionBottom - intersectionTop;\n const totalArea = pageWidth * pageHeight;\n const visibleArea = visibleWidth * visibleHeight;\n\n visibilityMetrics.push({\n pageNumber: page.pageNumber,\n viewportX: intersectionLeft - viewportLeft,\n viewportY: intersectionTop - viewportTop,\n visiblePercentage: (visibleArea / totalArea) * 100,\n original: {\n pageX: (intersectionLeft - pageX) / scale,\n pageY: (intersectionTop - pageY) / scale,\n visibleWidth: visibleWidth / scale,\n visibleHeight: visibleHeight / scale,\n scale: 1,\n },\n scaled: {\n pageX: intersectionLeft - pageX,\n pageY: intersectionTop - pageY,\n visibleWidth,\n visibleHeight,\n scale,\n },\n });\n }\n });\n });\n\n return visibilityMetrics;\n }\n\n protected determineCurrentPage(\n visibilityMetrics: ScrollMetrics['pageVisibilityMetrics'],\n ): number {\n if (visibilityMetrics.length === 0) return 1;\n\n const maxVisibility = Math.max(...visibilityMetrics.map((m) => m.visiblePercentage));\n const mostVisiblePages = visibilityMetrics.filter((m) => m.visiblePercentage === maxVisibility);\n\n return mostVisiblePages.length === 1\n ? mostVisiblePages[0].pageNumber\n : mostVisiblePages.sort((a, b) => a.pageNumber - b.pageNumber)[0].pageNumber;\n }\n\n private getRectLocationForPage(\n pageNumber: number,\n virtualItems: VirtualItem[],\n totalContentSize?: Size,\n ): Rect | null {\n // Find the virtual item containing the page\n const item = virtualItems.find((item) => item.pageNumbers.includes(pageNumber));\n if (!item) return null;\n\n // Find the specific page layout for the requested page number\n const pageLayout = item.pageLayouts.find((layout) => layout.pageNumber === pageNumber);\n if (!pageLayout) return null;\n\n // Calculate centering offset for items that are narrower than the maximum width\n let centeringOffsetX = 0;\n if (totalContentSize) {\n const maxWidth = totalContentSize.width;\n if (item.width < maxWidth) {\n centeringOffsetX = (maxWidth - item.width) / 2;\n }\n }\n\n return {\n origin: {\n x: item.x + pageLayout.x + centeringOffsetX,\n y: item.y + pageLayout.y,\n },\n size: {\n width: pageLayout.width,\n height: pageLayout.height,\n },\n };\n }\n\n getScrollPositionForPage(\n pageNumber: number,\n virtualItems: VirtualItem[],\n scale: number,\n rotation: Rotation,\n pageCoordinates?: { x: number; y: number },\n ): Position | null {\n const totalContentSize = this.getTotalContentSize(virtualItems);\n const pageRect = this.getRectLocationForPage(pageNumber, virtualItems, totalContentSize);\n if (!pageRect) return null;\n\n const scaledBasePosition = scalePosition(pageRect.origin, scale);\n\n // If specific page coordinates are provided, add them to the base position\n if (pageCoordinates) {\n const rotatedSize = transformPosition(\n {\n width: pageRect.size.width,\n height: pageRect.size.height,\n },\n {\n x: pageCoordinates.x,\n y: pageCoordinates.y,\n },\n rotation,\n scale,\n );\n\n return {\n x: scaledBasePosition.x + rotatedSize.x + this.viewportGap,\n y: scaledBasePosition.y + rotatedSize.y + this.viewportGap,\n };\n }\n\n return {\n x: scaledBasePosition.x + this.viewportGap,\n y: scaledBasePosition.y + this.viewportGap,\n };\n }\n\n getRectPositionForPage(\n pageNumber: number,\n virtualItems: VirtualItem[],\n scale: number,\n rotation: Rotation,\n rect: Rect,\n ): Rect | null {\n const totalContentSize = this.getTotalContentSize(virtualItems);\n const pageRect = this.getRectLocationForPage(pageNumber, virtualItems, totalContentSize);\n if (!pageRect) return null;\n\n const scaledBasePosition = scalePosition(pageRect.origin, scale);\n\n const rotatedSize = transformRect(\n {\n width: pageRect.size.width,\n height: pageRect.size.height,\n },\n rect,\n rotation,\n scale,\n );\n\n return {\n origin: {\n x: scaledBasePosition.x + rotatedSize.origin.x,\n y: scaledBasePosition.y + rotatedSize.origin.y,\n },\n size: rotatedSize.size,\n };\n }\n}\n","import { PdfPageObjectWithRotatedSize } from '@embedpdf/models';\nimport { ViewportMetrics } from '@embedpdf/plugin-viewport';\nimport { BaseScrollStrategy, ScrollStrategyConfig } from './base-strategy';\nimport { VirtualItem, PageLayout } from '../types/virtual-item';\nimport { ScrollMetrics } from '../types';\n\nexport class VerticalScrollStrategy extends BaseScrollStrategy {\n constructor(config: ScrollStrategyConfig) {\n super(config);\n }\n\n createVirtualItems(pdfPageObject: PdfPageObjectWithRotatedSize[][]): VirtualItem[] {\n let yOffset = 0;\n return pdfPageObject.map((pagesInSpread, index) => {\n let pageX = 0;\n const pageLayouts: PageLayout[] = pagesInSpread.map((page) => {\n const layout: PageLayout = {\n pageNumber: page.index + 1,\n pageIndex: page.index,\n x: pageX,\n y: 0,\n width: page.size.width,\n height: page.size.height,\n rotatedWidth: page.rotatedSize.width,\n rotatedHeight: page.rotatedSize.height,\n };\n pageX += page.rotatedSize.width + this.pageGap;\n return layout;\n });\n const width = pagesInSpread.reduce(\n (sum, page, i) =>\n sum + page.rotatedSize.width + (i < pagesInSpread.length - 1 ? this.pageGap : 0),\n 0,\n );\n const height = Math.max(...pagesInSpread.map((p) => p.rotatedSize.height));\n const item: VirtualItem = {\n id: `item-${index}`,\n x: 0,\n y: yOffset,\n offset: yOffset,\n width,\n height,\n pageLayouts,\n pageNumbers: pagesInSpread.map((p) => p.index + 1),\n index,\n };\n yOffset += height + this.pageGap;\n return item;\n });\n }\n\n getTotalContentSize(virtualItems: VirtualItem[]): { width: number; height: number } {\n if (virtualItems.length === 0) return { width: 0, height: 0 };\n const maxWidth = Math.max(...virtualItems.map((item) => item.width));\n const totalHeight =\n virtualItems[virtualItems.length - 1].y + virtualItems[virtualItems.length - 1].height;\n return {\n width: maxWidth,\n height: totalHeight,\n };\n }\n\n protected getScrollOffset(viewport: ViewportMetrics): number {\n return viewport.scrollTop;\n }\n\n protected getClientSize(viewport: ViewportMetrics): number {\n return viewport.clientHeight;\n }\n}\n","import { PdfPageObjectWithRotatedSize } from '@embedpdf/models';\nimport { ViewportMetrics } from '@embedpdf/plugin-viewport';\nimport { BaseScrollStrategy, ScrollStrategyConfig } from './base-strategy';\nimport { VirtualItem, PageLayout } from '../types/virtual-item';\n\nexport class HorizontalScrollStrategy extends BaseScrollStrategy {\n constructor(config: ScrollStrategyConfig) {\n super(config);\n }\n\n createVirtualItems(pdfPageObject: PdfPageObjectWithRotatedSize[][]): VirtualItem[] {\n let xOffset = 0;\n return pdfPageObject.map((pagesInSpread, index) => {\n let pageX = 0;\n const pageLayouts: PageLayout[] = pagesInSpread.map((page) => {\n const layout: PageLayout = {\n pageNumber: page.index + 1,\n pageIndex: page.index,\n x: pageX,\n y: 0,\n width: page.size.width,\n height: page.size.height,\n rotatedWidth: page.rotatedSize.width,\n rotatedHeight: page.rotatedSize.height,\n };\n pageX += page.rotatedSize.width + this.pageGap;\n return layout;\n });\n const width = pagesInSpread.reduce(\n (sum, page, i) =>\n sum + page.rotatedSize.width + (i < pagesInSpread.length - 1 ? this.pageGap : 0),\n 0,\n );\n const height = Math.max(...pagesInSpread.map((p) => p.rotatedSize.height));\n const item: VirtualItem = {\n id: `item-${index}`,\n x: xOffset,\n y: 0,\n offset: xOffset,\n width,\n height,\n pageLayouts,\n pageNumbers: pagesInSpread.map((p) => p.index + 1),\n index,\n };\n xOffset += width + this.pageGap;\n return item;\n });\n }\n\n getTotalContentSize(virtualItems: VirtualItem[]): { width: number; height: number } {\n if (virtualItems.length === 0) return { width: 0, height: 0 };\n const totalWidth =\n virtualItems[virtualItems.length - 1].x + virtualItems[virtualItems.length - 1].width;\n const maxHeight = Math.max(...virtualItems.map((item) => item.height));\n return {\n width: totalWidth,\n height: maxHeight,\n };\n }\n\n protected getScrollOffset(viewport: ViewportMetrics): number {\n return viewport.scrollLeft;\n }\n\n protected getClientSize(viewport: ViewportMetrics): number {\n return viewport.clientWidth;\n }\n}\n","import { Action } from '@embedpdf/core';\nimport { PageChangeState, ScrollState } from './types';\n\nexport const UPDATE_SCROLL_STATE = 'UPDATE_SCROLL_STATE';\nexport const SET_DESIRED_SCROLL_POSITION = 'SET_DESIRED_SCROLL_POSITION';\nexport const UPDATE_TOTAL_PAGES = 'UPDATE_TOTAL_PAGES';\nexport const SET_PAGE_CHANGE_STATE = 'SET_PAGE_CHANGE_STATE';\n\nexport interface UpdateScrollStateAction extends Action {\n type: typeof UPDATE_SCROLL_STATE;\n payload: Partial<ScrollState>;\n}\n\nexport interface SetDesiredScrollPositionAction extends Action {\n type: typeof SET_DESIRED_SCROLL_POSITION;\n payload: { x: number; y: number };\n}\n\nexport interface UpdateTotalPagesAction extends Action {\n type: typeof UPDATE_TOTAL_PAGES;\n payload: number;\n}\n\nexport interface SetPageChangeStateAction extends Action {\n type: typeof SET_PAGE_CHANGE_STATE;\n payload: PageChangeState;\n}\n\nexport type ScrollAction =\n | UpdateScrollStateAction\n | SetDesiredScrollPositionAction\n | UpdateTotalPagesAction\n | SetPageChangeStateAction;\n\nexport function updateScrollState(payload: Partial<ScrollState>): UpdateScrollStateAction {\n return { type: UPDATE_SCROLL_STATE, payload };\n}\n\nexport function setDesiredScrollPosition(payload: {\n x: number;\n y: number;\n}): SetDesiredScrollPositionAction {\n return { type: SET_DESIRED_SCROLL_POSITION, payload };\n}\n\nexport function updateTotalPages(payload: number): UpdateTotalPagesAction {\n return { type: UPDATE_TOTAL_PAGES, payload };\n}\n\nexport function setPageChangeState(payload: PageChangeState): SetPageChangeStateAction {\n return { type: SET_PAGE_CHANGE_STATE, payload };\n}\n","import { ScrollerLayout, ScrollState } from './types';\n\nexport const getScrollerLayout = (state: ScrollState, scale: number): ScrollerLayout => {\n return {\n startSpacing: state.startSpacing,\n endSpacing: state.endSpacing,\n totalWidth: state.totalContentSize.width * scale,\n totalHeight: state.totalContentSize.height * scale,\n pageGap: state.pageGap * scale,\n strategy: state.strategy,\n items: state.renderedPageIndexes.map((idx) => {\n return {\n ...state.virtualItems[idx],\n pageLayouts: state.virtualItems[idx].pageLayouts.map((layout) => {\n return {\n ...layout,\n rotatedWidth: layout.rotatedWidth * scale,\n rotatedHeight: layout.rotatedHeight * scale,\n width: layout.width * scale,\n height: layout.height * scale,\n };\n }),\n };\n }),\n };\n};\n","import {\n BasePlugin,\n CoreState,\n PluginRegistry,\n SET_DOCUMENT,\n SET_PAGES,\n SET_ROTATION,\n StoreState,\n Unsubscribe,\n createBehaviorEmitter,\n getPagesWithRotatedSize,\n} from '@embedpdf/core';\nimport { PdfPageObjectWithRotatedSize, Rect, Rotation } from '@embedpdf/models';\nimport { ViewportCapability, ViewportMetrics, ViewportPlugin } from '@embedpdf/plugin-viewport';\nimport {\n ScrollCapability,\n ScrollPluginConfig,\n ScrollStrategy,\n ScrollMetrics,\n ScrollState,\n LayoutChangePayload,\n ScrollerLayout,\n ScrollToPageOptions,\n PageChangePayload,\n ScrollBehavior,\n PageChangeState,\n} from './types';\nimport { BaseScrollStrategy, ScrollStrategyConfig } from './strategies/base-strategy';\nimport { VerticalScrollStrategy } from './strategies/vertical-strategy';\nimport { HorizontalScrollStrategy } from './strategies/horizontal-strategy';\nimport { updateScrollState, ScrollAction, updateTotalPages, setPageChangeState } from './actions';\nimport { VirtualItem } from './types/virtual-item';\nimport { getScrollerLayout } from './selectors';\n\ntype PartialScroll = Partial<ScrollState>;\ntype Emits = {\n layout?: LayoutChangePayload;\n metrics?: ScrollMetrics;\n};\n\nexport class ScrollPlugin extends BasePlugin<\n ScrollPluginConfig,\n ScrollCapability,\n ScrollState,\n ScrollAction\n> {\n static readonly id = 'scroll' as const;\n private viewport: ViewportCapability;\n private strategy: BaseScrollStrategy;\n private strategyConfig: ScrollStrategyConfig;\n private currentScale: number = 1;\n private currentRotation: Rotation = Rotation.Degree0;\n private initialPage?: number;\n private currentPage: number = 1;\n private layoutReady: boolean = false;\n\n private readonly pageChangeState$ = createBehaviorEmitter<PageChangeState>();\n private readonly layout$ = createBehaviorEmitter<LayoutChangePayload>();\n private readonly scroll$ = createBehaviorEmitter<ScrollMetrics>();\n private readonly state$ = createBehaviorEmitter<ScrollState>();\n private readonly scrollerLayout$ = createBehaviorEmitter<ScrollerLayout>();\n private readonly pageChange$ = createBehaviorEmitter<PageChangePayload>();\n private readonly layoutReady$ = createBehaviorEmitter<boolean>();\n\n constructor(\n public readonly id: string,\n registry: PluginRegistry,\n private config?: ScrollPluginConfig,\n ) {\n super(id, registry);\n\n this.viewport = this.registry.getPlugin<ViewportPlugin>('viewport')!.provides();\n\n this.strategyConfig = {\n pageGap: this.config?.pageGap ?? 10,\n viewportGap: this.viewport.getViewportGap(),\n bufferSize: this.config?.bufferSize ?? 2,\n };\n\n this.strategy =\n this.config?.strategy === ScrollStrategy.Horizontal\n ? new HorizontalScrollStrategy(this.strategyConfig)\n : new VerticalScrollStrategy(this.strategyConfig);\n\n this.initialPage = this.config?.initialPage;\n this.currentScale = this.coreState.core.scale;\n this.currentRotation = this.coreState.core.rotation;\n // Subscribe to viewport scroll activity to detect when smooth scrolling ends\n this.viewport.onScrollActivity((activity) => {\n if (this.state.pageChangeState.isChanging && !activity.isSmoothScrolling) {\n // Smooth scrolling has ended\n this.completePageChange();\n }\n });\n // Subscribe to viewport and page manager events\n this.viewport.onViewportChange((vp) => this.commitMetrics(this.computeMetrics(vp)), {\n mode: 'throttle',\n wait: 100,\n });\n this.coreStore.onAction(SET_DOCUMENT, (_action, state) => {\n const totalPages = state.core.pages.length;\n this.dispatch(updateTotalPages(totalPages));\n this.pageChange$.emit({ pageNumber: this.currentPage, totalPages });\n this.refreshAll(getPagesWithRotatedSize(state.core), this.viewport.getMetrics());\n });\n this.coreStore.onAction(SET_ROTATION, (_action, state) =>\n this.refreshAll(getPagesWithRotatedSize(state.core), this.viewport.getMetrics()),\n );\n this.coreStore.onAction(SET_PAGES, (_action, state) =>\n this.refreshAll(getPagesWithRotatedSize(state.core), this.viewport.getMetrics()),\n );\n }\n\n private startPageChange(targetPage: number, behavior: ScrollBehavior = 'smooth') {\n const pageChangeState: PageChangeState = {\n isChanging: true,\n targetPage,\n fromPage: this.currentPage,\n startTime: Date.now(),\n };\n\n this.dispatch(setPageChangeState(pageChangeState));\n\n // For instant behavior, complete immediately\n if (behavior === 'instant') {\n // Use setTimeout to ensure the scroll happens first\n this.completePageChange();\n }\n }\n\n private completePageChange() {\n if (!this.state.pageChangeState.isChanging) return;\n\n const pageChangeState: PageChangeState = {\n isChanging: false,\n targetPage: this.state.pageChangeState.targetPage,\n fromPage: this.state.pageChangeState.fromPage,\n startTime: this.state.pageChangeState.startTime,\n };\n\n this.dispatch(setPageChangeState(pageChangeState));\n }\n\n /* ------------------------------------------------------------------ */\n /* ᴄᴏᴍᴘᴜᴛᴇʀs */\n /* ------------------------------------------------------------------ */\n\n private computeLayout(pages: PdfPageObjectWithRotatedSize[][]) {\n const virtualItems = this.strategy.createVirtualItems(pages);\n const totalContentSize = this.strategy.getTotalContentSize(virtualItems);\n return { virtualItems, totalContentSize };\n }\n\n private computeMetrics(vp: ViewportMetrics, items: VirtualItem[] = this.state.virtualItems) {\n return this.strategy.handleScroll(vp, items, this.currentScale);\n }\n\n /* ------------------------------------------------------------------ */\n /* ᴄᴏᴍᴍɪᴛ (single source of truth) */\n /* ------------------------------------------------------------------ */\n\n private commit(stateDelta: PartialScroll, emit?: Emits) {\n /* update Redux-like store */\n this.dispatch(updateScrollState(stateDelta));\n\n /* fire optional events */\n if (emit?.layout) this.layout$.emit(emit.layout);\n if (emit?.metrics) {\n this.scroll$.emit(emit.metrics);\n\n if (emit.metrics.currentPage !== this.currentPage) {\n this.currentPage = emit.metrics.currentPage;\n this.pageChange$.emit({ pageNumber: this.currentPage, totalPages: this.state.totalPages });\n }\n }\n\n /* keep scroller-layout reactive */\n this.scrollerLayout$.emit(this.getScrollerLayout());\n }\n\n /* convenience wrappers */\n private commitMetrics(metrics: ScrollMetrics) {\n this.commit(metrics, { metrics });\n }\n\n /* full re-compute after page-spread or initialisation */\n private refreshAll(pages: PdfPageObjectWithRotatedSize[][], vp: ViewportMetrics) {\n const layout = this.computeLayout(pages);\n const metrics = this.computeMetrics(vp, layout.virtualItems);\n\n this.commit({ ...layout, ...metrics }, { layout, metrics });\n }\n\n private getVirtualItemsFromState(): VirtualItem[] {\n return this.state.virtualItems || [];\n }\n\n public onScrollerData(callback: (layout: ScrollerLayout) => void): Unsubscribe {\n return this.scrollerLayout$.on(callback);\n }\n\n public getScrollerLayout(): ScrollerLayout {\n const scale = this.coreState.core.scale;\n return getScrollerLayout(this.state, scale);\n }\n\n private pushScrollLayout() {\n this.scrollerLayout$.emit(this.getScrollerLayout());\n }\n\n override onStoreUpdated(prevState: ScrollState, newState: ScrollState): void {\n this.pushScrollLayout();\n\n if (prevState.pageChangeState !== newState.pageChangeState) {\n this.pageChangeState$.emit(newState.pageChangeState);\n }\n }\n\n override onCoreStoreUpdated(\n prevState: StoreState<CoreState>,\n newState: StoreState<CoreState>,\n ): void {\n if (prevState.core.scale !== newState.core.scale) {\n this.currentScale = newState.core.scale;\n this.commitMetrics(this.computeMetrics(this.viewport.getMetrics()));\n }\n if (prevState.core.rotation !== newState.core.rotation) {\n this.currentRotation = newState.core.rotation;\n }\n }\n\n /**\n * Change the scroll strategy at runtime (e.g., vertical <-> horizontal)\n * @param newStrategy ScrollStrategy.Horizontal or ScrollStrategy.Vertical\n */\n private setScrollStrategy(newStrategy: ScrollStrategy) {\n // Only update if the strategy is actually changing\n if (\n (newStrategy === ScrollStrategy.Horizontal &&\n this.strategy instanceof HorizontalScrollStrategy) ||\n (newStrategy === ScrollStrategy.Vertical && this.strategy instanceof VerticalScrollStrategy)\n ) {\n return;\n }\n\n this.strategy =\n newStrategy === ScrollStrategy.Horizontal\n ? new HorizontalScrollStrategy(this.strategyConfig)\n : new VerticalScrollStrategy(this.strategyConfig);\n\n // Update state with new strategy\n this.dispatch(\n updateScrollState({\n strategy: newStrategy,\n }),\n );\n\n // Recalculate layout and scroll metrics\n const pages = getPagesWithRotatedSize(this.coreState.core);\n this.refreshAll(pages, this.viewport.getMetrics());\n }\n\n public setLayoutReady() {\n if (this.layoutReady) return;\n\n this.layoutReady = true;\n this.layoutReady$.emit(true);\n\n if (this.initialPage) {\n this.scrollToPage({ pageNumber: this.initialPage, behavior: 'instant' });\n }\n }\n\n protected buildCapability(): ScrollCapability {\n return {\n onStateChange: this.state$.on,\n onLayoutChange: this.layout$.on,\n onScroll: this.scroll$.on,\n onPageChange: this.pageChange$.on,\n onLayoutReady: this.layoutReady$.on,\n onPageChangeState: this.pageChangeState$.on,\n getCurrentPage: () => this.currentPage,\n getTotalPages: () => this.state.totalPages,\n getPageChangeState: () => this.state.pageChangeState,\n scrollToPage: this.scrollToPage.bind(this),\n scrollToNextPage: this.scrollToNextPage.bind(this),\n scrollToPreviousPage: this.scrollToPreviousPage.bind(this),\n getMetrics: this.getMetrics.bind(this),\n getLayout: this.getLayout.bind(this),\n getRectPositionForPage: this.getRectPositionForPage.bind(this),\n getPageGap: () => this.state.pageGap,\n setScrollStrategy: (strategy: ScrollStrategy) => this.setScrollStrategy(strategy),\n };\n }\n\n private scrollToPage(options: ScrollToPageOptions) {\n const { pageNumber, behavior = 'smooth', pageCoordinates, center = false } = options;\n this.startPageChange(pageNumber, behavior);\n const virtualItems = this.getVirtualItemsFromState();\n const position = this.strategy.getScrollPositionForPage(\n pageNumber,\n virtualItems,\n this.currentScale,\n this.currentRotation,\n pageCoordinates,\n );\n if (position) {\n this.viewport.scrollTo({ ...position, behavior, center });\n } else {\n // If we couldn't find the position, complete the page change immediately\n this.completePageChange();\n }\n }\n\n private scrollToNextPage(behavior: ScrollBehavior = 'smooth') {\n const virtualItems = this.getVirtualItemsFromState();\n const currentItemIndex = virtualItems.findIndex((item) =>\n item.pageNumbers.includes(this.currentPage),\n );\n if (currentItemIndex >= 0 && currentItemIndex < virtualItems.length - 1) {\n const nextItem = virtualItems[currentItemIndex + 1];\n const targetPage = nextItem.pageNumbers[0];\n this.startPageChange(targetPage, behavior);\n\n const position = this.strategy.getScrollPositionForPage(\n nextItem.pageNumbers[0],\n virtualItems,\n this.currentScale,\n this.currentRotation,\n );\n if (position) {\n this.viewport.scrollTo({ ...position, behavior });\n } else {\n // If we couldn't find the position, complete the page change immediately\n this.completePageChange();\n }\n }\n }\n\n private scrollToPreviousPage(behavior: ScrollBehavior = 'smooth') {\n const virtualItems = this.getVirtualItemsFromState();\n const currentItemIndex = virtualItems.findIndex((item) =>\n item.pageNumbers.includes(this.currentPage),\n );\n if (currentItemIndex > 0) {\n const prevItem = virtualItems[currentItemIndex - 1];\n const targetPage = prevItem.pageNumbers[0];\n this.startPageChange(targetPage, behavior);\n\n const position = this.strategy.getScrollPositionForPage(\n prevItem.pageNumbers[0],\n virtualItems,\n this.currentScale,\n this.currentRotation,\n );\n if (position) {\n this.viewport.scrollTo({ ...position, behavior });\n } else {\n // If we couldn't find the position, complete the page change immediately\n this.completePageChange();\n }\n }\n }\n\n private getMetrics(viewport?: ViewportMetrics): ScrollMetrics {\n const metrics = viewport || this.viewport.getMetrics();\n const virtualItems = this.getVirtualItemsFromState();\n return this.strategy.handleScroll(metrics, virtualItems, this.currentScale);\n }\n\n private getLayout(): LayoutChangePayload {\n return {\n virtualItems: this.state.virtualItems,\n totalContentSize: this.state.totalContentSize,\n };\n }\n\n private getRectPositionForPage(\n pageIndex: number,\n rect: Rect,\n scale?: number,\n rotation?: Rotation,\n ): Rect | null {\n return this.strategy.getRectPositionForPage(\n pageIndex + 1,\n this.state.virtualItems,\n scale ?? this.currentScale,\n rotation ?? this.currentRotation,\n rect,\n );\n }\n\n async initialize(): Promise<void> {\n // No DOM initialization needed; state drives rendering\n }\n\n async destroy(): Promise<void> {\n this.layout$.clear();\n this.scroll$.clear();\n this.pageChange$.clear();\n this.state$.clear();\n this.scrollerLayout$.clear();\n this.layoutReady$.clear();\n this.pageChangeState$.clear();\n super.destroy();\n }\n}\n","import { PluginManifest } from '@embedpdf/core';\nimport { ScrollPluginConfig } from './types';\n\nexport const SCROLL_PLUGIN_ID = 'scroll';\n\nexport const manifest: PluginManifest<ScrollPluginConfig> = {\n id: SCROLL_PLUGIN_ID,\n name: 'Scroll Plugin',\n version: '1.0.0',\n provides: ['scroll'],\n requires: ['viewport'],\n optional: [],\n defaultConfig: {\n enabled: true,\n pageGap: 10,\n },\n};\n","import { Reducer, CoreState, SET_SCALE, SetScaleAction } from '@embedpdf/core';\nimport {\n ScrollState,\n ScrollStrategy,\n ScrollPluginConfig,\n ScrollMetrics,\n PageChangeState,\n} from './types';\nimport {\n ScrollAction,\n UPDATE_SCROLL_STATE,\n SET_DESIRED_SCROLL_POSITION,\n UPDATE_TOTAL_PAGES,\n SET_PAGE_CHANGE_STATE,\n} from './actions';\n\nexport const defaultScrollMetrics: ScrollMetrics = {\n currentPage: 1,\n visiblePages: [],\n pageVisibilityMetrics: [],\n renderedPageIndexes: [],\n scrollOffset: { x: 0, y: 0 },\n startSpacing: 0,\n endSpacing: 0,\n};\n\nexport const defaultPageChangeState: PageChangeState = {\n isChanging: false,\n targetPage: 1,\n fromPage: 1,\n startTime: 0,\n};\n\nexport const initialState: (coreState: CoreState, config: ScrollPluginConfig) => ScrollState = (\n coreState,\n config,\n) => ({\n virtualItems: [],\n totalPages: coreState.pages.length,\n totalContentSize: { width: 0, height: 0 },\n desiredScrollPosition: { x: 0, y: 0 },\n strategy: config.strategy ?? ScrollStrategy.Vertical,\n pageGap: config.pageGap ?? 10,\n scale: coreState.scale,\n pageChangeState: defaultPageChangeState,\n ...defaultScrollMetrics,\n});\n\nexport const scrollReducer: Reducer<ScrollState, ScrollAction | SetScaleAction> = (\n state,\n action,\n) => {\n switch (action.type) {\n case UPDATE_TOTAL_PAGES:\n return { ...state, totalPages: action.payload };\n case SET_SCALE:\n return { ...state, scale: action.payload };\n case UPDATE_SCROLL_STATE:\n return { ...state, ...action.payload };\n case SET_DESIRED_SCROLL_POSITION:\n return { ...state, desiredScrollPosition: action.payload };\n case SET_PAGE_CHANGE_STATE:\n return { ...state, pageChangeState: action.payload };\n default:\n return state;\n }\n};\n","import { PluginPackage } from '@embedpdf/core';\nimport { ScrollPlugin } from './scroll-plugin';\nimport { manifest, SCROLL_PLUGIN_ID } from './manifest';\nimport { ScrollPluginConfig, ScrollState } from './types';\nimport { scrollReducer, initialState } from './reducer';\nimport { ScrollAction } from './actions';\n\nexport const ScrollPluginPackage: PluginPackage<\n ScrollPlugin,\n ScrollPluginConfig,\n ScrollState,\n ScrollAction\n> = {\n manifest,\n create: (registry, config) => new ScrollPlugin(SCROLL_PLUGIN_ID, registry, config),\n reducer: scrollReducer,\n initialState: (coreState, config) => initialState(coreState, config),\n};\n\nexport * from './scroll-plugin';\nexport * from './types';\nexport * from './manifest';\nexport * from './types/virtual-item';\n"],"names":["ScrollStrategy","BaseScrollStrategy","constructor","config","this","pageGap","viewportGap","bufferSize","getVisibleRange","viewport","virtualItems","scale","scrollOffset","getScrollOffset","viewportStart","viewportEnd","getClientSize","startIndex","length","offset","height","endIndex","start","Math","max","end","min","handleScroll","range","visibleItems","slice","pageVisibilityMetrics","calculatePageVisibility","visiblePages","map","m","pageNumber","renderedPageIndexes","flatMap","item","index","currentPage","determineCurrentPage","first","last","startSpacing","endSpacing","x","scrollLeft","y","scrollTop","visibilityMetrics","forEach","pageLayouts","page","itemX","itemY","pageX","pageY","pageWidth","rotatedWidth","pageHeight","rotatedHeight","viewportLeft","viewportTop","viewportRight","clientWidth","viewportBottom","clientHeight","intersectionLeft","intersectionTop","intersectionRight","intersectionBottom","visibleWidth","visibleHeight","totalArea","visibleArea","push","viewportX","viewportY","visiblePercentage","original","scaled","maxVisibility","mostVisiblePages","filter","sort","a","b","getRectLocationForPage","totalContentSize","find","pageNumbers","includes","pageLayout","layout","centeringOffsetX","maxWidth","width","origin","size","getScrollPositionForPage","rotation","pageCoordinates","getTotalContentSize","pageRect","scaledBasePosition","scalePosition","rotatedSize","transformPosition","getRectPositionForPage","rect","transformRect","VerticalScrollStrategy","super","createVirtualItems","pdfPageObject","yOffset","pagesInSpread","pageIndex","reduce","sum","i","p","id","HorizontalScrollStrategy","xOffset","UPDATE_SCROLL_STATE","UPDATE_TOTAL_PAGES","SET_PAGE_CHANGE_STATE","updateScrollState","payload","type","setPageChangeState","_ScrollPlugin","BasePlugin","registry","currentScale","currentRotation","Rotation","Degree0","layoutReady","pageChangeState$","createBehaviorEmitter","layout$","scroll$","state$","scrollerLayout$","pageChange$","layoutReady$","getPlugin","provides","strategyConfig","_a","getViewportGap","_b","strategy","_c","Horizontal","initialPage","_d","coreState","core","onScrollActivity","activity","state","pageChangeState","isChanging","isSmoothScrolling","completePageChange","onViewportChange","vp","commitMetrics","computeMetrics","mode","wait","coreStore","onAction","SET_DOCUMENT","_action","totalPages","pages","dispatch","emit","refreshAll","getPagesWithRotatedSize","getMetrics","SET_ROTATION","SET_PAGES","startPageChange","targetPage","behavior","fromPage","startTime","Date","now","computeLayout","items","commit","stateDelta","metrics","getScrollerLayout","getVirtualItemsFromState","onScrollerData","callback","on","totalWidth","totalHeight","idx","pushScrollLayout","onStoreUpdated","prevState","newState","onCoreStoreUpdated","setScrollStrategy","newStrategy","Vertical","setLayoutReady","scrollToPage","buildCapability","onStateChange","onLayoutChange","onScroll","onPageChange","onLayoutReady","onPageChangeState","getCurrentPage","getTotalPages","getPageChangeState","bind","scrollToNextPage","scrollToPreviousPage","getLayout","getPageGap","options","center","position","scrollTo","currentItemIndex","findIndex","nextItem","prevItem","initialize","destroy","clear","ScrollPlugin","SCROLL_PLUGIN_ID","manifest","name","version","requires","optional","defaultConfig","enabled","defaultScrollMetrics","defaultPageChangeState","ScrollPluginPackage","create","reducer","action","SET_SCALE","desiredScrollPosition","initialState"],"mappings":"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"}
|
package/dist/index.js
CHANGED
|
@@ -299,12 +299,16 @@ class HorizontalScrollStrategy extends BaseScrollStrategy {
|
|
|
299
299
|
const UPDATE_SCROLL_STATE = "UPDATE_SCROLL_STATE";
|
|
300
300
|
const SET_DESIRED_SCROLL_POSITION = "SET_DESIRED_SCROLL_POSITION";
|
|
301
301
|
const UPDATE_TOTAL_PAGES = "UPDATE_TOTAL_PAGES";
|
|
302
|
+
const SET_PAGE_CHANGE_STATE = "SET_PAGE_CHANGE_STATE";
|
|
302
303
|
function updateScrollState(payload) {
|
|
303
304
|
return { type: UPDATE_SCROLL_STATE, payload };
|
|
304
305
|
}
|
|
305
306
|
function updateTotalPages(payload) {
|
|
306
307
|
return { type: UPDATE_TOTAL_PAGES, payload };
|
|
307
308
|
}
|
|
309
|
+
function setPageChangeState(payload) {
|
|
310
|
+
return { type: SET_PAGE_CHANGE_STATE, payload };
|
|
311
|
+
}
|
|
308
312
|
const getScrollerLayout = (state, scale) => {
|
|
309
313
|
return {
|
|
310
314
|
startSpacing: state.startSpacing,
|
|
@@ -339,6 +343,7 @@ const _ScrollPlugin = class _ScrollPlugin extends BasePlugin {
|
|
|
339
343
|
this.currentRotation = Rotation.Degree0;
|
|
340
344
|
this.currentPage = 1;
|
|
341
345
|
this.layoutReady = false;
|
|
346
|
+
this.pageChangeState$ = createBehaviorEmitter();
|
|
342
347
|
this.layout$ = createBehaviorEmitter();
|
|
343
348
|
this.scroll$ = createBehaviorEmitter();
|
|
344
349
|
this.state$ = createBehaviorEmitter();
|
|
@@ -355,6 +360,11 @@ const _ScrollPlugin = class _ScrollPlugin extends BasePlugin {
|
|
|
355
360
|
this.initialPage = (_d = this.config) == null ? void 0 : _d.initialPage;
|
|
356
361
|
this.currentScale = this.coreState.core.scale;
|
|
357
362
|
this.currentRotation = this.coreState.core.rotation;
|
|
363
|
+
this.viewport.onScrollActivity((activity) => {
|
|
364
|
+
if (this.state.pageChangeState.isChanging && !activity.isSmoothScrolling) {
|
|
365
|
+
this.completePageChange();
|
|
366
|
+
}
|
|
367
|
+
});
|
|
358
368
|
this.viewport.onViewportChange((vp) => this.commitMetrics(this.computeMetrics(vp)), {
|
|
359
369
|
mode: "throttle",
|
|
360
370
|
wait: 100
|
|
@@ -374,6 +384,28 @@ const _ScrollPlugin = class _ScrollPlugin extends BasePlugin {
|
|
|
374
384
|
(_action, state) => this.refreshAll(getPagesWithRotatedSize(state.core), this.viewport.getMetrics())
|
|
375
385
|
);
|
|
376
386
|
}
|
|
387
|
+
startPageChange(targetPage, behavior = "smooth") {
|
|
388
|
+
const pageChangeState = {
|
|
389
|
+
isChanging: true,
|
|
390
|
+
targetPage,
|
|
391
|
+
fromPage: this.currentPage,
|
|
392
|
+
startTime: Date.now()
|
|
393
|
+
};
|
|
394
|
+
this.dispatch(setPageChangeState(pageChangeState));
|
|
395
|
+
if (behavior === "instant") {
|
|
396
|
+
this.completePageChange();
|
|
397
|
+
}
|
|
398
|
+
}
|
|
399
|
+
completePageChange() {
|
|
400
|
+
if (!this.state.pageChangeState.isChanging) return;
|
|
401
|
+
const pageChangeState = {
|
|
402
|
+
isChanging: false,
|
|
403
|
+
targetPage: this.state.pageChangeState.targetPage,
|
|
404
|
+
fromPage: this.state.pageChangeState.fromPage,
|
|
405
|
+
startTime: this.state.pageChangeState.startTime
|
|
406
|
+
};
|
|
407
|
+
this.dispatch(setPageChangeState(pageChangeState));
|
|
408
|
+
}
|
|
377
409
|
/* ------------------------------------------------------------------ */
|
|
378
410
|
/* ᴄᴏᴍᴘᴜᴛᴇʀs */
|
|
379
411
|
/* ------------------------------------------------------------------ */
|
|
@@ -423,8 +455,11 @@ const _ScrollPlugin = class _ScrollPlugin extends BasePlugin {
|
|
|
423
455
|
pushScrollLayout() {
|
|
424
456
|
this.scrollerLayout$.emit(this.getScrollerLayout());
|
|
425
457
|
}
|
|
426
|
-
onStoreUpdated(
|
|
458
|
+
onStoreUpdated(prevState, newState) {
|
|
427
459
|
this.pushScrollLayout();
|
|
460
|
+
if (prevState.pageChangeState !== newState.pageChangeState) {
|
|
461
|
+
this.pageChangeState$.emit(newState.pageChangeState);
|
|
462
|
+
}
|
|
428
463
|
}
|
|
429
464
|
onCoreStoreUpdated(prevState, newState) {
|
|
430
465
|
if (prevState.core.scale !== newState.core.scale) {
|
|
@@ -467,8 +502,10 @@ const _ScrollPlugin = class _ScrollPlugin extends BasePlugin {
|
|
|
467
502
|
onScroll: this.scroll$.on,
|
|
468
503
|
onPageChange: this.pageChange$.on,
|
|
469
504
|
onLayoutReady: this.layoutReady$.on,
|
|
505
|
+
onPageChangeState: this.pageChangeState$.on,
|
|
470
506
|
getCurrentPage: () => this.currentPage,
|
|
471
507
|
getTotalPages: () => this.state.totalPages,
|
|
508
|
+
getPageChangeState: () => this.state.pageChangeState,
|
|
472
509
|
scrollToPage: this.scrollToPage.bind(this),
|
|
473
510
|
scrollToNextPage: this.scrollToNextPage.bind(this),
|
|
474
511
|
scrollToPreviousPage: this.scrollToPreviousPage.bind(this),
|
|
@@ -481,6 +518,7 @@ const _ScrollPlugin = class _ScrollPlugin extends BasePlugin {
|
|
|
481
518
|
}
|
|
482
519
|
scrollToPage(options) {
|
|
483
520
|
const { pageNumber, behavior = "smooth", pageCoordinates, center = false } = options;
|
|
521
|
+
this.startPageChange(pageNumber, behavior);
|
|
484
522
|
const virtualItems = this.getVirtualItemsFromState();
|
|
485
523
|
const position = this.strategy.getScrollPositionForPage(
|
|
486
524
|
pageNumber,
|
|
@@ -491,6 +529,8 @@ const _ScrollPlugin = class _ScrollPlugin extends BasePlugin {
|
|
|
491
529
|
);
|
|
492
530
|
if (position) {
|
|
493
531
|
this.viewport.scrollTo({ ...position, behavior, center });
|
|
532
|
+
} else {
|
|
533
|
+
this.completePageChange();
|
|
494
534
|
}
|
|
495
535
|
}
|
|
496
536
|
scrollToNextPage(behavior = "smooth") {
|
|
@@ -500,6 +540,8 @@ const _ScrollPlugin = class _ScrollPlugin extends BasePlugin {
|
|
|
500
540
|
);
|
|
501
541
|
if (currentItemIndex >= 0 && currentItemIndex < virtualItems.length - 1) {
|
|
502
542
|
const nextItem = virtualItems[currentItemIndex + 1];
|
|
543
|
+
const targetPage = nextItem.pageNumbers[0];
|
|
544
|
+
this.startPageChange(targetPage, behavior);
|
|
503
545
|
const position = this.strategy.getScrollPositionForPage(
|
|
504
546
|
nextItem.pageNumbers[0],
|
|
505
547
|
virtualItems,
|
|
@@ -508,6 +550,8 @@ const _ScrollPlugin = class _ScrollPlugin extends BasePlugin {
|
|
|
508
550
|
);
|
|
509
551
|
if (position) {
|
|
510
552
|
this.viewport.scrollTo({ ...position, behavior });
|
|
553
|
+
} else {
|
|
554
|
+
this.completePageChange();
|
|
511
555
|
}
|
|
512
556
|
}
|
|
513
557
|
}
|
|
@@ -518,6 +562,8 @@ const _ScrollPlugin = class _ScrollPlugin extends BasePlugin {
|
|
|
518
562
|
);
|
|
519
563
|
if (currentItemIndex > 0) {
|
|
520
564
|
const prevItem = virtualItems[currentItemIndex - 1];
|
|
565
|
+
const targetPage = prevItem.pageNumbers[0];
|
|
566
|
+
this.startPageChange(targetPage, behavior);
|
|
521
567
|
const position = this.strategy.getScrollPositionForPage(
|
|
522
568
|
prevItem.pageNumbers[0],
|
|
523
569
|
virtualItems,
|
|
@@ -526,6 +572,8 @@ const _ScrollPlugin = class _ScrollPlugin extends BasePlugin {
|
|
|
526
572
|
);
|
|
527
573
|
if (position) {
|
|
528
574
|
this.viewport.scrollTo({ ...position, behavior });
|
|
575
|
+
} else {
|
|
576
|
+
this.completePageChange();
|
|
529
577
|
}
|
|
530
578
|
}
|
|
531
579
|
}
|
|
@@ -558,6 +606,7 @@ const _ScrollPlugin = class _ScrollPlugin extends BasePlugin {
|
|
|
558
606
|
this.state$.clear();
|
|
559
607
|
this.scrollerLayout$.clear();
|
|
560
608
|
this.layoutReady$.clear();
|
|
609
|
+
this.pageChangeState$.clear();
|
|
561
610
|
super.destroy();
|
|
562
611
|
}
|
|
563
612
|
};
|
|
@@ -585,6 +634,12 @@ const defaultScrollMetrics = {
|
|
|
585
634
|
startSpacing: 0,
|
|
586
635
|
endSpacing: 0
|
|
587
636
|
};
|
|
637
|
+
const defaultPageChangeState = {
|
|
638
|
+
isChanging: false,
|
|
639
|
+
targetPage: 1,
|
|
640
|
+
fromPage: 1,
|
|
641
|
+
startTime: 0
|
|
642
|
+
};
|
|
588
643
|
const initialState = (coreState, config) => ({
|
|
589
644
|
virtualItems: [],
|
|
590
645
|
totalPages: coreState.pages.length,
|
|
@@ -593,6 +648,7 @@ const initialState = (coreState, config) => ({
|
|
|
593
648
|
strategy: config.strategy ?? ScrollStrategy.Vertical,
|
|
594
649
|
pageGap: config.pageGap ?? 10,
|
|
595
650
|
scale: coreState.scale,
|
|
651
|
+
pageChangeState: defaultPageChangeState,
|
|
596
652
|
...defaultScrollMetrics
|
|
597
653
|
});
|
|
598
654
|
const scrollReducer = (state, action) => {
|
|
@@ -605,6 +661,8 @@ const scrollReducer = (state, action) => {
|
|
|
605
661
|
return { ...state, ...action.payload };
|
|
606
662
|
case SET_DESIRED_SCROLL_POSITION:
|
|
607
663
|
return { ...state, desiredScrollPosition: action.payload };
|
|
664
|
+
case SET_PAGE_CHANGE_STATE:
|
|
665
|
+
return { ...state, pageChangeState: action.payload };
|
|
608
666
|
default:
|
|
609
667
|
return state;
|
|
610
668
|
}
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sources":["../src/lib/types.ts","../src/lib/strategies/base-strategy.ts","../src/lib/strategies/vertical-strategy.ts","../src/lib/strategies/horizontal-strategy.ts","../src/lib/actions.ts","../src/lib/selectors.ts","../src/lib/scroll-plugin.ts","../src/lib/manifest.ts","../src/lib/reducer.ts","../src/lib/index.ts"],"sourcesContent":["import { BasePluginConfig, Emitter, EventHook } from '@embedpdf/core';\nimport { PdfPageObject, Rect, Rotation } from '@embedpdf/models';\nimport { ViewportMetrics } from '@embedpdf/plugin-viewport';\nimport { VirtualItem } from './types/virtual-item';\n\nexport type ScrollBehavior = 'instant' | 'smooth' | 'auto';\n\nexport interface ScrollState extends ScrollMetrics {\n virtualItems: VirtualItem[];\n totalPages: number;\n totalContentSize: { width: number; height: number };\n desiredScrollPosition: { x: number; y: number };\n strategy: ScrollStrategy;\n pageGap: number;\n scale: number;\n}\n\nexport interface ScrollerLayout {\n startSpacing: number;\n endSpacing: number;\n totalWidth: number;\n totalHeight: number;\n pageGap: number;\n strategy: ScrollState['strategy'];\n items: VirtualItem[];\n}\n\nexport enum ScrollStrategy {\n Vertical = 'vertical',\n Horizontal = 'horizontal',\n}\n\nexport interface PageVisibilityMetrics {\n pageNumber: number;\n viewportX: number;\n viewportY: number;\n visiblePercentage: number;\n original: {\n pageX: number;\n pageY: number;\n visibleWidth: number;\n visibleHeight: number;\n scale: number;\n };\n scaled: {\n pageX: number;\n pageY: number;\n visibleWidth: number;\n visibleHeight: number;\n scale: number;\n };\n}\n\nexport interface ScrollMetrics {\n currentPage: number;\n visiblePages: number[];\n pageVisibilityMetrics: PageVisibilityMetrics[];\n renderedPageIndexes: number[];\n scrollOffset: { x: number; y: number };\n startSpacing: number;\n endSpacing: number;\n}\n\nexport interface ScrollStrategyInterface {\n initialize(container: HTMLElement, innerDiv: HTMLElement): void;\n destroy(): void;\n updateLayout(viewport: ViewportMetrics, pdfPageObject: PdfPageObject[][]): void;\n handleScroll(viewport: ViewportMetrics): void;\n getVirtualItems(): VirtualItem[];\n scrollToPage(pageNumber: number, behavior?: ScrollBehavior): void;\n calculateDimensions(pdfPageObject: PdfPageObject[][]): void;\n}\n\nexport interface ScrollPluginConfig extends BasePluginConfig {\n strategy?: ScrollStrategy;\n initialPage?: number;\n bufferSize?: number;\n pageGap?: number;\n}\n\nexport type LayoutChangePayload = Pick<ScrollState, 'virtualItems' | 'totalContentSize'>;\n\nexport interface ScrollToPageOptions {\n pageNumber: number;\n pageCoordinates?: { x: number; y: number };\n behavior?: ScrollBehavior;\n center?: boolean;\n}\n\nexport interface PageChangePayload {\n pageNumber: number;\n totalPages: number;\n}\n\nexport interface ScrollCapability {\n onStateChange: EventHook<ScrollState>;\n onScroll: EventHook<ScrollMetrics>;\n getCurrentPage(): number;\n getTotalPages(): number;\n onPageChange: EventHook<PageChangePayload>;\n onLayoutChange: EventHook<LayoutChangePayload>;\n onLayoutReady: EventHook<boolean>;\n scrollToPage(options: ScrollToPageOptions): void;\n scrollToNextPage(behavior?: ScrollBehavior): void;\n scrollToPreviousPage(behavior?: ScrollBehavior): void;\n getMetrics(viewport?: ViewportMetrics): ScrollMetrics;\n getLayout(): LayoutChangePayload;\n getRectPositionForPage(\n page: number,\n rect: Rect,\n scale?: number,\n rotation?: Rotation,\n ): Rect | null;\n setScrollStrategy(strategy: ScrollStrategy): void;\n getPageGap(): number;\n}\n","import {\n PdfPageObjectWithRotatedSize,\n Position,\n Rect,\n Rotation,\n scalePosition,\n Size,\n transformPosition,\n transformRect,\n} from '@embedpdf/models';\nimport { ViewportMetrics } from '@embedpdf/plugin-viewport';\nimport { VirtualItem } from '../types/virtual-item';\nimport { ScrollMetrics } from '../types';\n\nexport interface ScrollStrategyConfig {\n pageGap?: number;\n viewportGap?: number;\n bufferSize?: number;\n}\n\nexport abstract class BaseScrollStrategy {\n protected pageGap: number;\n protected viewportGap: number;\n protected bufferSize: number;\n\n constructor(config: ScrollStrategyConfig) {\n this.pageGap = config.pageGap ?? 20;\n this.viewportGap = config.viewportGap ?? 20;\n this.bufferSize = config.bufferSize ?? 2;\n }\n\n abstract createVirtualItems(pdfPageObject: PdfPageObjectWithRotatedSize[][]): VirtualItem[];\n abstract getTotalContentSize(virtualItems: VirtualItem[]): Size;\n protected abstract getScrollOffset(viewport: ViewportMetrics): number;\n protected abstract getClientSize(viewport: ViewportMetrics): number;\n\n protected getVisibleRange(\n viewport: ViewportMetrics,\n virtualItems: VirtualItem[],\n scale: number,\n ): { start: number; end: number } {\n const scrollOffset = this.getScrollOffset(viewport);\n const clientSize = this.getClientSize(viewport);\n const viewportStart = scrollOffset;\n const viewportEnd = scrollOffset + clientSize;\n\n let startIndex = 0;\n while (\n startIndex < virtualItems.length &&\n (virtualItems[startIndex].offset + virtualItems[startIndex].height) * scale <= viewportStart\n ) {\n startIndex++;\n }\n\n let endIndex = startIndex;\n while (endIndex < virtualItems.length && virtualItems[endIndex].offset * scale <= viewportEnd) {\n endIndex++;\n }\n\n return {\n start: Math.max(0, startIndex - this.bufferSize),\n end: Math.min(virtualItems.length - 1, endIndex + this.bufferSize - 1),\n };\n }\n\n handleScroll(\n viewport: ViewportMetrics,\n virtualItems: VirtualItem[],\n scale: number,\n ): ScrollMetrics {\n const range = this.getVisibleRange(viewport, virtualItems, scale);\n const visibleItems = virtualItems.slice(range.start, range.end + 1);\n const pageVisibilityMetrics = this.calculatePageVisibility(visibleItems, viewport, scale);\n const visiblePages = pageVisibilityMetrics.map((m) => m.pageNumber);\n const renderedPageIndexes = virtualItems\n .slice(range.start, range.end + 1)\n .flatMap((item) => item.index);\n const currentPage = this.determineCurrentPage(pageVisibilityMetrics);\n const first = virtualItems[range.start];\n const last = virtualItems[range.end];\n const startSpacing = first ? first.offset * scale : 0;\n const endSpacing = last\n ? (virtualItems[virtualItems.length - 1].offset + // end of content\n virtualItems[virtualItems.length - 1].height) *\n scale - // minus\n (last.offset + last.height) * scale // end of last rendered\n : 0;\n\n return {\n currentPage,\n visiblePages,\n pageVisibilityMetrics,\n renderedPageIndexes,\n scrollOffset: { x: viewport.scrollLeft, y: viewport.scrollTop },\n startSpacing,\n endSpacing,\n };\n }\n\n protected calculatePageVisibility(\n virtualItems: VirtualItem[],\n viewport: ViewportMetrics,\n scale: number,\n ): ScrollMetrics['pageVisibilityMetrics'] {\n const visibilityMetrics: ScrollMetrics['pageVisibilityMetrics'] = [];\n\n virtualItems.forEach((item) => {\n item.pageLayouts.forEach((page) => {\n const itemX = item.x * scale;\n const itemY = item.y * scale;\n const pageX = itemX + page.x * scale;\n const pageY = itemY + page.y * scale;\n const pageWidth = page.rotatedWidth * scale;\n const pageHeight = page.rotatedHeight * scale;\n\n const viewportLeft = viewport.scrollLeft;\n const viewportTop = viewport.scrollTop;\n const viewportRight = viewportLeft + viewport.clientWidth;\n const viewportBottom = viewportTop + viewport.clientHeight;\n\n const intersectionLeft = Math.max(pageX, viewportLeft);\n const intersectionTop = Math.max(pageY, viewportTop);\n const intersectionRight = Math.min(pageX + pageWidth, viewportRight);\n const intersectionBottom = Math.min(pageY + pageHeight, viewportBottom);\n\n if (intersectionLeft < intersectionRight && intersectionTop < intersectionBottom) {\n const visibleWidth = intersectionRight - intersectionLeft;\n const visibleHeight = intersectionBottom - intersectionTop;\n const totalArea = pageWidth * pageHeight;\n const visibleArea = visibleWidth * visibleHeight;\n\n visibilityMetrics.push({\n pageNumber: page.pageNumber,\n viewportX: intersectionLeft - viewportLeft,\n viewportY: intersectionTop - viewportTop,\n visiblePercentage: (visibleArea / totalArea) * 100,\n original: {\n pageX: (intersectionLeft - pageX) / scale,\n pageY: (intersectionTop - pageY) / scale,\n visibleWidth: visibleWidth / scale,\n visibleHeight: visibleHeight / scale,\n scale: 1,\n },\n scaled: {\n pageX: intersectionLeft - pageX,\n pageY: intersectionTop - pageY,\n visibleWidth,\n visibleHeight,\n scale,\n },\n });\n }\n });\n });\n\n return visibilityMetrics;\n }\n\n protected determineCurrentPage(\n visibilityMetrics: ScrollMetrics['pageVisibilityMetrics'],\n ): number {\n if (visibilityMetrics.length === 0) return 1;\n\n const maxVisibility = Math.max(...visibilityMetrics.map((m) => m.visiblePercentage));\n const mostVisiblePages = visibilityMetrics.filter((m) => m.visiblePercentage === maxVisibility);\n\n return mostVisiblePages.length === 1\n ? mostVisiblePages[0].pageNumber\n : mostVisiblePages.sort((a, b) => a.pageNumber - b.pageNumber)[0].pageNumber;\n }\n\n private getRectLocationForPage(\n pageNumber: number,\n virtualItems: VirtualItem[],\n totalContentSize?: Size,\n ): Rect | null {\n // Find the virtual item containing the page\n const item = virtualItems.find((item) => item.pageNumbers.includes(pageNumber));\n if (!item) return null;\n\n // Find the specific page layout for the requested page number\n const pageLayout = item.pageLayouts.find((layout) => layout.pageNumber === pageNumber);\n if (!pageLayout) return null;\n\n // Calculate centering offset for items that are narrower than the maximum width\n let centeringOffsetX = 0;\n if (totalContentSize) {\n const maxWidth = totalContentSize.width;\n if (item.width < maxWidth) {\n centeringOffsetX = (maxWidth - item.width) / 2;\n }\n }\n\n return {\n origin: {\n x: item.x + pageLayout.x + centeringOffsetX,\n y: item.y + pageLayout.y,\n },\n size: {\n width: pageLayout.width,\n height: pageLayout.height,\n },\n };\n }\n\n getScrollPositionForPage(\n pageNumber: number,\n virtualItems: VirtualItem[],\n scale: number,\n rotation: Rotation,\n pageCoordinates?: { x: number; y: number },\n ): Position | null {\n const totalContentSize = this.getTotalContentSize(virtualItems);\n const pageRect = this.getRectLocationForPage(pageNumber, virtualItems, totalContentSize);\n if (!pageRect) return null;\n\n const scaledBasePosition = scalePosition(pageRect.origin, scale);\n\n // If specific page coordinates are provided, add them to the base position\n if (pageCoordinates) {\n const rotatedSize = transformPosition(\n {\n width: pageRect.size.width,\n height: pageRect.size.height,\n },\n {\n x: pageCoordinates.x,\n y: pageCoordinates.y,\n },\n rotation,\n scale,\n );\n\n return {\n x: scaledBasePosition.x + rotatedSize.x + this.viewportGap,\n y: scaledBasePosition.y + rotatedSize.y + this.viewportGap,\n };\n }\n\n return {\n x: scaledBasePosition.x + this.viewportGap,\n y: scaledBasePosition.y + this.viewportGap,\n };\n }\n\n getRectPositionForPage(\n pageNumber: number,\n virtualItems: VirtualItem[],\n scale: number,\n rotation: Rotation,\n rect: Rect,\n ): Rect | null {\n const totalContentSize = this.getTotalContentSize(virtualItems);\n const pageRect = this.getRectLocationForPage(pageNumber, virtualItems, totalContentSize);\n if (!pageRect) return null;\n\n const scaledBasePosition = scalePosition(pageRect.origin, scale);\n\n const rotatedSize = transformRect(\n {\n width: pageRect.size.width,\n height: pageRect.size.height,\n },\n rect,\n rotation,\n scale,\n );\n\n return {\n origin: {\n x: scaledBasePosition.x + rotatedSize.origin.x,\n y: scaledBasePosition.y + rotatedSize.origin.y,\n },\n size: rotatedSize.size,\n };\n }\n}\n","import { PdfPageObjectWithRotatedSize } from '@embedpdf/models';\nimport { ViewportMetrics } from '@embedpdf/plugin-viewport';\nimport { BaseScrollStrategy, ScrollStrategyConfig } from './base-strategy';\nimport { VirtualItem, PageLayout } from '../types/virtual-item';\nimport { ScrollMetrics } from '../types';\n\nexport class VerticalScrollStrategy extends BaseScrollStrategy {\n constructor(config: ScrollStrategyConfig) {\n super(config);\n }\n\n createVirtualItems(pdfPageObject: PdfPageObjectWithRotatedSize[][]): VirtualItem[] {\n let yOffset = 0;\n return pdfPageObject.map((pagesInSpread, index) => {\n let pageX = 0;\n const pageLayouts: PageLayout[] = pagesInSpread.map((page) => {\n const layout: PageLayout = {\n pageNumber: page.index + 1,\n pageIndex: page.index,\n x: pageX,\n y: 0,\n width: page.size.width,\n height: page.size.height,\n rotatedWidth: page.rotatedSize.width,\n rotatedHeight: page.rotatedSize.height,\n };\n pageX += page.rotatedSize.width + this.pageGap;\n return layout;\n });\n const width = pagesInSpread.reduce(\n (sum, page, i) =>\n sum + page.rotatedSize.width + (i < pagesInSpread.length - 1 ? this.pageGap : 0),\n 0,\n );\n const height = Math.max(...pagesInSpread.map((p) => p.rotatedSize.height));\n const item: VirtualItem = {\n id: `item-${index}`,\n x: 0,\n y: yOffset,\n offset: yOffset,\n width,\n height,\n pageLayouts,\n pageNumbers: pagesInSpread.map((p) => p.index + 1),\n index,\n };\n yOffset += height + this.pageGap;\n return item;\n });\n }\n\n getTotalContentSize(virtualItems: VirtualItem[]): { width: number; height: number } {\n if (virtualItems.length === 0) return { width: 0, height: 0 };\n const maxWidth = Math.max(...virtualItems.map((item) => item.width));\n const totalHeight =\n virtualItems[virtualItems.length - 1].y + virtualItems[virtualItems.length - 1].height;\n return {\n width: maxWidth,\n height: totalHeight,\n };\n }\n\n protected getScrollOffset(viewport: ViewportMetrics): number {\n return viewport.scrollTop;\n }\n\n protected getClientSize(viewport: ViewportMetrics): number {\n return viewport.clientHeight;\n }\n}\n","import { PdfPageObjectWithRotatedSize } from '@embedpdf/models';\nimport { ViewportMetrics } from '@embedpdf/plugin-viewport';\nimport { BaseScrollStrategy, ScrollStrategyConfig } from './base-strategy';\nimport { VirtualItem, PageLayout } from '../types/virtual-item';\n\nexport class HorizontalScrollStrategy extends BaseScrollStrategy {\n constructor(config: ScrollStrategyConfig) {\n super(config);\n }\n\n createVirtualItems(pdfPageObject: PdfPageObjectWithRotatedSize[][]): VirtualItem[] {\n let xOffset = 0;\n return pdfPageObject.map((pagesInSpread, index) => {\n let pageX = 0;\n const pageLayouts: PageLayout[] = pagesInSpread.map((page) => {\n const layout: PageLayout = {\n pageNumber: page.index + 1,\n pageIndex: page.index,\n x: pageX,\n y: 0,\n width: page.size.width,\n height: page.size.height,\n rotatedWidth: page.rotatedSize.width,\n rotatedHeight: page.rotatedSize.height,\n };\n pageX += page.rotatedSize.width + this.pageGap;\n return layout;\n });\n const width = pagesInSpread.reduce(\n (sum, page, i) =>\n sum + page.rotatedSize.width + (i < pagesInSpread.length - 1 ? this.pageGap : 0),\n 0,\n );\n const height = Math.max(...pagesInSpread.map((p) => p.rotatedSize.height));\n const item: VirtualItem = {\n id: `item-${index}`,\n x: xOffset,\n y: 0,\n offset: xOffset,\n width,\n height,\n pageLayouts,\n pageNumbers: pagesInSpread.map((p) => p.index + 1),\n index,\n };\n xOffset += width + this.pageGap;\n return item;\n });\n }\n\n getTotalContentSize(virtualItems: VirtualItem[]): { width: number; height: number } {\n if (virtualItems.length === 0) return { width: 0, height: 0 };\n const totalWidth =\n virtualItems[virtualItems.length - 1].x + virtualItems[virtualItems.length - 1].width;\n const maxHeight = Math.max(...virtualItems.map((item) => item.height));\n return {\n width: totalWidth,\n height: maxHeight,\n };\n }\n\n protected getScrollOffset(viewport: ViewportMetrics): number {\n return viewport.scrollLeft;\n }\n\n protected getClientSize(viewport: ViewportMetrics): number {\n return viewport.clientWidth;\n }\n}\n","import { Action } from '@embedpdf/core';\nimport { ScrollState } from './types';\n\nexport const UPDATE_SCROLL_STATE = 'UPDATE_SCROLL_STATE';\nexport const SET_DESIRED_SCROLL_POSITION = 'SET_DESIRED_SCROLL_POSITION';\nexport const UPDATE_TOTAL_PAGES = 'UPDATE_TOTAL_PAGES';\n\nexport interface UpdateScrollStateAction extends Action {\n type: typeof UPDATE_SCROLL_STATE;\n payload: Partial<ScrollState>;\n}\n\nexport interface SetDesiredScrollPositionAction extends Action {\n type: typeof SET_DESIRED_SCROLL_POSITION;\n payload: { x: number; y: number };\n}\n\nexport interface UpdateTotalPagesAction extends Action {\n type: typeof UPDATE_TOTAL_PAGES;\n payload: number;\n}\n\nexport type ScrollAction =\n | UpdateScrollStateAction\n | SetDesiredScrollPositionAction\n | UpdateTotalPagesAction;\n\nexport function updateScrollState(payload: Partial<ScrollState>): UpdateScrollStateAction {\n return { type: UPDATE_SCROLL_STATE, payload };\n}\n\nexport function setDesiredScrollPosition(payload: {\n x: number;\n y: number;\n}): SetDesiredScrollPositionAction {\n return { type: SET_DESIRED_SCROLL_POSITION, payload };\n}\n\nexport function updateTotalPages(payload: number): UpdateTotalPagesAction {\n return { type: UPDATE_TOTAL_PAGES, payload };\n}\n","import { ScrollerLayout, ScrollState } from './types';\n\nexport const getScrollerLayout = (state: ScrollState, scale: number): ScrollerLayout => {\n return {\n startSpacing: state.startSpacing,\n endSpacing: state.endSpacing,\n totalWidth: state.totalContentSize.width * scale,\n totalHeight: state.totalContentSize.height * scale,\n pageGap: state.pageGap * scale,\n strategy: state.strategy,\n items: state.renderedPageIndexes.map((idx) => {\n return {\n ...state.virtualItems[idx],\n pageLayouts: state.virtualItems[idx].pageLayouts.map((layout) => {\n return {\n ...layout,\n rotatedWidth: layout.rotatedWidth * scale,\n rotatedHeight: layout.rotatedHeight * scale,\n width: layout.width * scale,\n height: layout.height * scale,\n };\n }),\n };\n }),\n };\n};\n","import {\n BasePlugin,\n CoreState,\n PluginRegistry,\n SET_DOCUMENT,\n SET_PAGES,\n SET_ROTATION,\n StoreState,\n Unsubscribe,\n createBehaviorEmitter,\n getPagesWithRotatedSize,\n} from '@embedpdf/core';\nimport { PdfPageObjectWithRotatedSize, Rect, Rotation } from '@embedpdf/models';\nimport { ViewportCapability, ViewportMetrics, ViewportPlugin } from '@embedpdf/plugin-viewport';\nimport {\n ScrollCapability,\n ScrollPluginConfig,\n ScrollStrategy,\n ScrollMetrics,\n ScrollState,\n LayoutChangePayload,\n ScrollerLayout,\n ScrollToPageOptions,\n PageChangePayload,\n ScrollBehavior,\n} from './types';\nimport { BaseScrollStrategy, ScrollStrategyConfig } from './strategies/base-strategy';\nimport { VerticalScrollStrategy } from './strategies/vertical-strategy';\nimport { HorizontalScrollStrategy } from './strategies/horizontal-strategy';\nimport { updateScrollState, ScrollAction, updateTotalPages } from './actions';\nimport { VirtualItem } from './types/virtual-item';\nimport { getScrollerLayout } from './selectors';\n\ntype PartialScroll = Partial<ScrollState>;\ntype Emits = {\n layout?: LayoutChangePayload;\n metrics?: ScrollMetrics;\n};\n\nexport class ScrollPlugin extends BasePlugin<\n ScrollPluginConfig,\n ScrollCapability,\n ScrollState,\n ScrollAction\n> {\n static readonly id = 'scroll' as const;\n private viewport: ViewportCapability;\n private strategy: BaseScrollStrategy;\n private strategyConfig: ScrollStrategyConfig;\n private currentScale: number = 1;\n private currentRotation: Rotation = Rotation.Degree0;\n private initialPage?: number;\n private currentPage: number = 1;\n private layoutReady: boolean = false;\n\n private readonly layout$ = createBehaviorEmitter<LayoutChangePayload>();\n private readonly scroll$ = createBehaviorEmitter<ScrollMetrics>();\n private readonly state$ = createBehaviorEmitter<ScrollState>();\n private readonly scrollerLayout$ = createBehaviorEmitter<ScrollerLayout>();\n private readonly pageChange$ = createBehaviorEmitter<PageChangePayload>();\n private readonly layoutReady$ = createBehaviorEmitter<boolean>();\n\n constructor(\n public readonly id: string,\n registry: PluginRegistry,\n private config?: ScrollPluginConfig,\n ) {\n super(id, registry);\n\n this.viewport = this.registry.getPlugin<ViewportPlugin>('viewport')!.provides();\n\n this.strategyConfig = {\n pageGap: this.config?.pageGap ?? 10,\n viewportGap: this.viewport.getViewportGap(),\n bufferSize: this.config?.bufferSize ?? 2,\n };\n\n this.strategy =\n this.config?.strategy === ScrollStrategy.Horizontal\n ? new HorizontalScrollStrategy(this.strategyConfig)\n : new VerticalScrollStrategy(this.strategyConfig);\n\n this.initialPage = this.config?.initialPage;\n this.currentScale = this.coreState.core.scale;\n this.currentRotation = this.coreState.core.rotation;\n // Subscribe to viewport and page manager events\n this.viewport.onViewportChange((vp) => this.commitMetrics(this.computeMetrics(vp)), {\n mode: 'throttle',\n wait: 100,\n });\n this.coreStore.onAction(SET_DOCUMENT, (_action, state) => {\n const totalPages = state.core.pages.length;\n this.dispatch(updateTotalPages(totalPages));\n this.pageChange$.emit({ pageNumber: this.currentPage, totalPages });\n this.refreshAll(getPagesWithRotatedSize(state.core), this.viewport.getMetrics());\n });\n this.coreStore.onAction(SET_ROTATION, (_action, state) =>\n this.refreshAll(getPagesWithRotatedSize(state.core), this.viewport.getMetrics()),\n );\n this.coreStore.onAction(SET_PAGES, (_action, state) =>\n this.refreshAll(getPagesWithRotatedSize(state.core), this.viewport.getMetrics()),\n );\n }\n\n /* ------------------------------------------------------------------ */\n /* ᴄᴏᴍᴘᴜᴛᴇʀs */\n /* ------------------------------------------------------------------ */\n\n private computeLayout(pages: PdfPageObjectWithRotatedSize[][]) {\n const virtualItems = this.strategy.createVirtualItems(pages);\n const totalContentSize = this.strategy.getTotalContentSize(virtualItems);\n return { virtualItems, totalContentSize };\n }\n\n private computeMetrics(vp: ViewportMetrics, items: VirtualItem[] = this.state.virtualItems) {\n return this.strategy.handleScroll(vp, items, this.currentScale);\n }\n\n /* ------------------------------------------------------------------ */\n /* ᴄᴏᴍᴍɪᴛ (single source of truth) */\n /* ------------------------------------------------------------------ */\n\n private commit(stateDelta: PartialScroll, emit?: Emits) {\n /* update Redux-like store */\n this.dispatch(updateScrollState(stateDelta));\n\n /* fire optional events */\n if (emit?.layout) this.layout$.emit(emit.layout);\n if (emit?.metrics) {\n this.scroll$.emit(emit.metrics);\n\n if (emit.metrics.currentPage !== this.currentPage) {\n this.currentPage = emit.metrics.currentPage;\n this.pageChange$.emit({ pageNumber: this.currentPage, totalPages: this.state.totalPages });\n }\n }\n\n /* keep scroller-layout reactive */\n this.scrollerLayout$.emit(this.getScrollerLayout());\n }\n\n /* convenience wrappers */\n private commitMetrics(metrics: ScrollMetrics) {\n this.commit(metrics, { metrics });\n }\n\n /* full re-compute after page-spread or initialisation */\n private refreshAll(pages: PdfPageObjectWithRotatedSize[][], vp: ViewportMetrics) {\n const layout = this.computeLayout(pages);\n const metrics = this.computeMetrics(vp, layout.virtualItems);\n\n this.commit({ ...layout, ...metrics }, { layout, metrics });\n }\n\n private getVirtualItemsFromState(): VirtualItem[] {\n return this.state.virtualItems || [];\n }\n\n public onScrollerData(callback: (layout: ScrollerLayout) => void): Unsubscribe {\n return this.scrollerLayout$.on(callback);\n }\n\n public getScrollerLayout(): ScrollerLayout {\n const scale = this.coreState.core.scale;\n return getScrollerLayout(this.state, scale);\n }\n\n private pushScrollLayout() {\n this.scrollerLayout$.emit(this.getScrollerLayout());\n }\n\n override onStoreUpdated(_prevState: ScrollState, _newState: ScrollState): void {\n this.pushScrollLayout();\n }\n\n override onCoreStoreUpdated(\n prevState: StoreState<CoreState>,\n newState: StoreState<CoreState>,\n ): void {\n if (prevState.core.scale !== newState.core.scale) {\n this.currentScale = newState.core.scale;\n this.commitMetrics(this.computeMetrics(this.viewport.getMetrics()));\n }\n if (prevState.core.rotation !== newState.core.rotation) {\n this.currentRotation = newState.core.rotation;\n }\n }\n\n /**\n * Change the scroll strategy at runtime (e.g., vertical <-> horizontal)\n * @param newStrategy ScrollStrategy.Horizontal or ScrollStrategy.Vertical\n */\n private setScrollStrategy(newStrategy: ScrollStrategy) {\n // Only update if the strategy is actually changing\n if (\n (newStrategy === ScrollStrategy.Horizontal &&\n this.strategy instanceof HorizontalScrollStrategy) ||\n (newStrategy === ScrollStrategy.Vertical && this.strategy instanceof VerticalScrollStrategy)\n ) {\n return;\n }\n\n this.strategy =\n newStrategy === ScrollStrategy.Horizontal\n ? new HorizontalScrollStrategy(this.strategyConfig)\n : new VerticalScrollStrategy(this.strategyConfig);\n\n // Update state with new strategy\n this.dispatch(\n updateScrollState({\n strategy: newStrategy,\n }),\n );\n\n // Recalculate layout and scroll metrics\n const pages = getPagesWithRotatedSize(this.coreState.core);\n this.refreshAll(pages, this.viewport.getMetrics());\n }\n\n public setLayoutReady() {\n if (this.layoutReady) return;\n\n this.layoutReady = true;\n this.layoutReady$.emit(true);\n\n if (this.initialPage) {\n this.scrollToPage({ pageNumber: this.initialPage, behavior: 'instant' });\n }\n }\n\n protected buildCapability(): ScrollCapability {\n return {\n onStateChange: this.state$.on,\n onLayoutChange: this.layout$.on,\n onScroll: this.scroll$.on,\n onPageChange: this.pageChange$.on,\n onLayoutReady: this.layoutReady$.on,\n getCurrentPage: () => this.currentPage,\n getTotalPages: () => this.state.totalPages,\n scrollToPage: this.scrollToPage.bind(this),\n scrollToNextPage: this.scrollToNextPage.bind(this),\n scrollToPreviousPage: this.scrollToPreviousPage.bind(this),\n getMetrics: this.getMetrics.bind(this),\n getLayout: this.getLayout.bind(this),\n getRectPositionForPage: this.getRectPositionForPage.bind(this),\n getPageGap: () => this.state.pageGap,\n setScrollStrategy: (strategy: ScrollStrategy) => this.setScrollStrategy(strategy),\n };\n }\n\n private scrollToPage(options: ScrollToPageOptions) {\n const { pageNumber, behavior = 'smooth', pageCoordinates, center = false } = options;\n const virtualItems = this.getVirtualItemsFromState();\n const position = this.strategy.getScrollPositionForPage(\n pageNumber,\n virtualItems,\n this.currentScale,\n this.currentRotation,\n pageCoordinates,\n );\n if (position) {\n this.viewport.scrollTo({ ...position, behavior, center });\n }\n }\n\n private scrollToNextPage(behavior: ScrollBehavior = 'smooth') {\n const virtualItems = this.getVirtualItemsFromState();\n const currentItemIndex = virtualItems.findIndex((item) =>\n item.pageNumbers.includes(this.currentPage),\n );\n if (currentItemIndex >= 0 && currentItemIndex < virtualItems.length - 1) {\n const nextItem = virtualItems[currentItemIndex + 1];\n const position = this.strategy.getScrollPositionForPage(\n nextItem.pageNumbers[0],\n virtualItems,\n this.currentScale,\n this.currentRotation,\n );\n if (position) {\n this.viewport.scrollTo({ ...position, behavior });\n }\n }\n }\n\n private scrollToPreviousPage(behavior: ScrollBehavior = 'smooth') {\n const virtualItems = this.getVirtualItemsFromState();\n const currentItemIndex = virtualItems.findIndex((item) =>\n item.pageNumbers.includes(this.currentPage),\n );\n if (currentItemIndex > 0) {\n const prevItem = virtualItems[currentItemIndex - 1];\n const position = this.strategy.getScrollPositionForPage(\n prevItem.pageNumbers[0],\n virtualItems,\n this.currentScale,\n this.currentRotation,\n );\n if (position) {\n this.viewport.scrollTo({ ...position, behavior });\n }\n }\n }\n\n private getMetrics(viewport?: ViewportMetrics): ScrollMetrics {\n const metrics = viewport || this.viewport.getMetrics();\n const virtualItems = this.getVirtualItemsFromState();\n return this.strategy.handleScroll(metrics, virtualItems, this.currentScale);\n }\n\n private getLayout(): LayoutChangePayload {\n return {\n virtualItems: this.state.virtualItems,\n totalContentSize: this.state.totalContentSize,\n };\n }\n\n private getRectPositionForPage(\n pageIndex: number,\n rect: Rect,\n scale?: number,\n rotation?: Rotation,\n ): Rect | null {\n return this.strategy.getRectPositionForPage(\n pageIndex + 1,\n this.state.virtualItems,\n scale ?? this.currentScale,\n rotation ?? this.currentRotation,\n rect,\n );\n }\n\n async initialize(): Promise<void> {\n // No DOM initialization needed; state drives rendering\n }\n\n async destroy(): Promise<void> {\n this.layout$.clear();\n this.scroll$.clear();\n this.pageChange$.clear();\n this.state$.clear();\n this.scrollerLayout$.clear();\n this.layoutReady$.clear();\n super.destroy();\n }\n}\n","import { PluginManifest } from '@embedpdf/core';\nimport { ScrollPluginConfig } from './types';\n\nexport const SCROLL_PLUGIN_ID = 'scroll';\n\nexport const manifest: PluginManifest<ScrollPluginConfig> = {\n id: SCROLL_PLUGIN_ID,\n name: 'Scroll Plugin',\n version: '1.0.0',\n provides: ['scroll'],\n requires: ['viewport'],\n optional: [],\n defaultConfig: {\n enabled: true,\n pageGap: 10,\n },\n};\n","import { Reducer, CoreState, SET_SCALE, SetScaleAction } from '@embedpdf/core';\nimport { ScrollState, ScrollStrategy, ScrollPluginConfig, ScrollMetrics } from './types';\nimport {\n ScrollAction,\n UPDATE_SCROLL_STATE,\n SET_DESIRED_SCROLL_POSITION,\n UPDATE_TOTAL_PAGES,\n} from './actions';\n\nexport const defaultScrollMetrics: ScrollMetrics = {\n currentPage: 1,\n visiblePages: [],\n pageVisibilityMetrics: [],\n renderedPageIndexes: [],\n scrollOffset: { x: 0, y: 0 },\n startSpacing: 0,\n endSpacing: 0,\n};\n\nexport const initialState: (coreState: CoreState, config: ScrollPluginConfig) => ScrollState = (\n coreState,\n config,\n) => ({\n virtualItems: [],\n totalPages: coreState.pages.length,\n totalContentSize: { width: 0, height: 0 },\n desiredScrollPosition: { x: 0, y: 0 },\n strategy: config.strategy ?? ScrollStrategy.Vertical,\n pageGap: config.pageGap ?? 10,\n scale: coreState.scale,\n ...defaultScrollMetrics,\n});\n\nexport const scrollReducer: Reducer<ScrollState, ScrollAction | SetScaleAction> = (\n state,\n action,\n) => {\n switch (action.type) {\n case UPDATE_TOTAL_PAGES:\n return { ...state, totalPages: action.payload };\n case SET_SCALE:\n return { ...state, scale: action.payload };\n case UPDATE_SCROLL_STATE:\n return { ...state, ...action.payload };\n case SET_DESIRED_SCROLL_POSITION:\n return { ...state, desiredScrollPosition: action.payload };\n default:\n return state;\n }\n};\n","import { PluginPackage } from '@embedpdf/core';\nimport { ScrollPlugin } from './scroll-plugin';\nimport { manifest, SCROLL_PLUGIN_ID } from './manifest';\nimport { ScrollPluginConfig, ScrollState } from './types';\nimport { scrollReducer, initialState } from './reducer';\nimport { ScrollAction } from './actions';\n\nexport const ScrollPluginPackage: PluginPackage<\n ScrollPlugin,\n ScrollPluginConfig,\n ScrollState,\n ScrollAction\n> = {\n manifest,\n create: (registry, config) => new ScrollPlugin(SCROLL_PLUGIN_ID, registry, config),\n reducer: scrollReducer,\n initialState: (coreState, config) => initialState(coreState, config),\n};\n\nexport * from './scroll-plugin';\nexport * from './types';\nexport * from './manifest';\nexport * from './types/virtual-item';\n"],"names":["ScrollStrategy","item"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","sources":["../src/lib/types.ts","../src/lib/strategies/base-strategy.ts","../src/lib/strategies/vertical-strategy.ts","../src/lib/strategies/horizontal-strategy.ts","../src/lib/actions.ts","../src/lib/selectors.ts","../src/lib/scroll-plugin.ts","../src/lib/manifest.ts","../src/lib/reducer.ts","../src/lib/index.ts"],"sourcesContent":["import { BasePluginConfig, Emitter, EventHook } from '@embedpdf/core';\nimport { PdfPageObject, Rect, Rotation } from '@embedpdf/models';\nimport { ViewportMetrics } from '@embedpdf/plugin-viewport';\nimport { VirtualItem } from './types/virtual-item';\n\nexport type ScrollBehavior = 'instant' | 'smooth' | 'auto';\n\nexport interface PageChangeState {\n isChanging: boolean;\n targetPage: number;\n fromPage: number;\n startTime: number;\n}\n\nexport interface ScrollState extends ScrollMetrics {\n virtualItems: VirtualItem[];\n totalPages: number;\n totalContentSize: { width: number; height: number };\n desiredScrollPosition: { x: number; y: number };\n strategy: ScrollStrategy;\n pageGap: number;\n scale: number;\n pageChangeState: PageChangeState;\n}\n\nexport interface ScrollerLayout {\n startSpacing: number;\n endSpacing: number;\n totalWidth: number;\n totalHeight: number;\n pageGap: number;\n strategy: ScrollState['strategy'];\n items: VirtualItem[];\n}\n\nexport enum ScrollStrategy {\n Vertical = 'vertical',\n Horizontal = 'horizontal',\n}\n\nexport interface PageVisibilityMetrics {\n pageNumber: number;\n viewportX: number;\n viewportY: number;\n visiblePercentage: number;\n original: {\n pageX: number;\n pageY: number;\n visibleWidth: number;\n visibleHeight: number;\n scale: number;\n };\n scaled: {\n pageX: number;\n pageY: number;\n visibleWidth: number;\n visibleHeight: number;\n scale: number;\n };\n}\n\nexport interface ScrollMetrics {\n currentPage: number;\n visiblePages: number[];\n pageVisibilityMetrics: PageVisibilityMetrics[];\n renderedPageIndexes: number[];\n scrollOffset: { x: number; y: number };\n startSpacing: number;\n endSpacing: number;\n}\n\nexport interface ScrollStrategyInterface {\n initialize(container: HTMLElement, innerDiv: HTMLElement): void;\n destroy(): void;\n updateLayout(viewport: ViewportMetrics, pdfPageObject: PdfPageObject[][]): void;\n handleScroll(viewport: ViewportMetrics): void;\n getVirtualItems(): VirtualItem[];\n scrollToPage(pageNumber: number, behavior?: ScrollBehavior): void;\n calculateDimensions(pdfPageObject: PdfPageObject[][]): void;\n}\n\nexport interface ScrollPluginConfig extends BasePluginConfig {\n strategy?: ScrollStrategy;\n initialPage?: number;\n bufferSize?: number;\n pageGap?: number;\n}\n\nexport type LayoutChangePayload = Pick<ScrollState, 'virtualItems' | 'totalContentSize'>;\n\nexport interface ScrollToPageOptions {\n pageNumber: number;\n pageCoordinates?: { x: number; y: number };\n behavior?: ScrollBehavior;\n center?: boolean;\n}\n\nexport interface PageChangePayload {\n pageNumber: number;\n totalPages: number;\n}\n\nexport interface ScrollCapability {\n onStateChange: EventHook<ScrollState>;\n onScroll: EventHook<ScrollMetrics>;\n getCurrentPage(): number;\n getTotalPages(): number;\n getPageChangeState(): PageChangeState;\n onPageChange: EventHook<PageChangePayload>;\n onLayoutChange: EventHook<LayoutChangePayload>;\n onPageChangeState: EventHook<PageChangeState>;\n onLayoutReady: EventHook<boolean>;\n scrollToPage(options: ScrollToPageOptions): void;\n scrollToNextPage(behavior?: ScrollBehavior): void;\n scrollToPreviousPage(behavior?: ScrollBehavior): void;\n getMetrics(viewport?: ViewportMetrics): ScrollMetrics;\n getLayout(): LayoutChangePayload;\n getRectPositionForPage(\n page: number,\n rect: Rect,\n scale?: number,\n rotation?: Rotation,\n ): Rect | null;\n setScrollStrategy(strategy: ScrollStrategy): void;\n getPageGap(): number;\n getPageChangeState: () => PageChangeState;\n}\n","import {\n PdfPageObjectWithRotatedSize,\n Position,\n Rect,\n Rotation,\n scalePosition,\n Size,\n transformPosition,\n transformRect,\n} from '@embedpdf/models';\nimport { ViewportMetrics } from '@embedpdf/plugin-viewport';\nimport { VirtualItem } from '../types/virtual-item';\nimport { ScrollMetrics } from '../types';\n\nexport interface ScrollStrategyConfig {\n pageGap?: number;\n viewportGap?: number;\n bufferSize?: number;\n}\n\nexport abstract class BaseScrollStrategy {\n protected pageGap: number;\n protected viewportGap: number;\n protected bufferSize: number;\n\n constructor(config: ScrollStrategyConfig) {\n this.pageGap = config.pageGap ?? 20;\n this.viewportGap = config.viewportGap ?? 20;\n this.bufferSize = config.bufferSize ?? 2;\n }\n\n abstract createVirtualItems(pdfPageObject: PdfPageObjectWithRotatedSize[][]): VirtualItem[];\n abstract getTotalContentSize(virtualItems: VirtualItem[]): Size;\n protected abstract getScrollOffset(viewport: ViewportMetrics): number;\n protected abstract getClientSize(viewport: ViewportMetrics): number;\n\n protected getVisibleRange(\n viewport: ViewportMetrics,\n virtualItems: VirtualItem[],\n scale: number,\n ): { start: number; end: number } {\n const scrollOffset = this.getScrollOffset(viewport);\n const clientSize = this.getClientSize(viewport);\n const viewportStart = scrollOffset;\n const viewportEnd = scrollOffset + clientSize;\n\n let startIndex = 0;\n while (\n startIndex < virtualItems.length &&\n (virtualItems[startIndex].offset + virtualItems[startIndex].height) * scale <= viewportStart\n ) {\n startIndex++;\n }\n\n let endIndex = startIndex;\n while (endIndex < virtualItems.length && virtualItems[endIndex].offset * scale <= viewportEnd) {\n endIndex++;\n }\n\n return {\n start: Math.max(0, startIndex - this.bufferSize),\n end: Math.min(virtualItems.length - 1, endIndex + this.bufferSize - 1),\n };\n }\n\n handleScroll(\n viewport: ViewportMetrics,\n virtualItems: VirtualItem[],\n scale: number,\n ): ScrollMetrics {\n const range = this.getVisibleRange(viewport, virtualItems, scale);\n const visibleItems = virtualItems.slice(range.start, range.end + 1);\n const pageVisibilityMetrics = this.calculatePageVisibility(visibleItems, viewport, scale);\n const visiblePages = pageVisibilityMetrics.map((m) => m.pageNumber);\n const renderedPageIndexes = virtualItems\n .slice(range.start, range.end + 1)\n .flatMap((item) => item.index);\n const currentPage = this.determineCurrentPage(pageVisibilityMetrics);\n const first = virtualItems[range.start];\n const last = virtualItems[range.end];\n const startSpacing = first ? first.offset * scale : 0;\n const endSpacing = last\n ? (virtualItems[virtualItems.length - 1].offset + // end of content\n virtualItems[virtualItems.length - 1].height) *\n scale - // minus\n (last.offset + last.height) * scale // end of last rendered\n : 0;\n\n return {\n currentPage,\n visiblePages,\n pageVisibilityMetrics,\n renderedPageIndexes,\n scrollOffset: { x: viewport.scrollLeft, y: viewport.scrollTop },\n startSpacing,\n endSpacing,\n };\n }\n\n protected calculatePageVisibility(\n virtualItems: VirtualItem[],\n viewport: ViewportMetrics,\n scale: number,\n ): ScrollMetrics['pageVisibilityMetrics'] {\n const visibilityMetrics: ScrollMetrics['pageVisibilityMetrics'] = [];\n\n virtualItems.forEach((item) => {\n item.pageLayouts.forEach((page) => {\n const itemX = item.x * scale;\n const itemY = item.y * scale;\n const pageX = itemX + page.x * scale;\n const pageY = itemY + page.y * scale;\n const pageWidth = page.rotatedWidth * scale;\n const pageHeight = page.rotatedHeight * scale;\n\n const viewportLeft = viewport.scrollLeft;\n const viewportTop = viewport.scrollTop;\n const viewportRight = viewportLeft + viewport.clientWidth;\n const viewportBottom = viewportTop + viewport.clientHeight;\n\n const intersectionLeft = Math.max(pageX, viewportLeft);\n const intersectionTop = Math.max(pageY, viewportTop);\n const intersectionRight = Math.min(pageX + pageWidth, viewportRight);\n const intersectionBottom = Math.min(pageY + pageHeight, viewportBottom);\n\n if (intersectionLeft < intersectionRight && intersectionTop < intersectionBottom) {\n const visibleWidth = intersectionRight - intersectionLeft;\n const visibleHeight = intersectionBottom - intersectionTop;\n const totalArea = pageWidth * pageHeight;\n const visibleArea = visibleWidth * visibleHeight;\n\n visibilityMetrics.push({\n pageNumber: page.pageNumber,\n viewportX: intersectionLeft - viewportLeft,\n viewportY: intersectionTop - viewportTop,\n visiblePercentage: (visibleArea / totalArea) * 100,\n original: {\n pageX: (intersectionLeft - pageX) / scale,\n pageY: (intersectionTop - pageY) / scale,\n visibleWidth: visibleWidth / scale,\n visibleHeight: visibleHeight / scale,\n scale: 1,\n },\n scaled: {\n pageX: intersectionLeft - pageX,\n pageY: intersectionTop - pageY,\n visibleWidth,\n visibleHeight,\n scale,\n },\n });\n }\n });\n });\n\n return visibilityMetrics;\n }\n\n protected determineCurrentPage(\n visibilityMetrics: ScrollMetrics['pageVisibilityMetrics'],\n ): number {\n if (visibilityMetrics.length === 0) return 1;\n\n const maxVisibility = Math.max(...visibilityMetrics.map((m) => m.visiblePercentage));\n const mostVisiblePages = visibilityMetrics.filter((m) => m.visiblePercentage === maxVisibility);\n\n return mostVisiblePages.length === 1\n ? mostVisiblePages[0].pageNumber\n : mostVisiblePages.sort((a, b) => a.pageNumber - b.pageNumber)[0].pageNumber;\n }\n\n private getRectLocationForPage(\n pageNumber: number,\n virtualItems: VirtualItem[],\n totalContentSize?: Size,\n ): Rect | null {\n // Find the virtual item containing the page\n const item = virtualItems.find((item) => item.pageNumbers.includes(pageNumber));\n if (!item) return null;\n\n // Find the specific page layout for the requested page number\n const pageLayout = item.pageLayouts.find((layout) => layout.pageNumber === pageNumber);\n if (!pageLayout) return null;\n\n // Calculate centering offset for items that are narrower than the maximum width\n let centeringOffsetX = 0;\n if (totalContentSize) {\n const maxWidth = totalContentSize.width;\n if (item.width < maxWidth) {\n centeringOffsetX = (maxWidth - item.width) / 2;\n }\n }\n\n return {\n origin: {\n x: item.x + pageLayout.x + centeringOffsetX,\n y: item.y + pageLayout.y,\n },\n size: {\n width: pageLayout.width,\n height: pageLayout.height,\n },\n };\n }\n\n getScrollPositionForPage(\n pageNumber: number,\n virtualItems: VirtualItem[],\n scale: number,\n rotation: Rotation,\n pageCoordinates?: { x: number; y: number },\n ): Position | null {\n const totalContentSize = this.getTotalContentSize(virtualItems);\n const pageRect = this.getRectLocationForPage(pageNumber, virtualItems, totalContentSize);\n if (!pageRect) return null;\n\n const scaledBasePosition = scalePosition(pageRect.origin, scale);\n\n // If specific page coordinates are provided, add them to the base position\n if (pageCoordinates) {\n const rotatedSize = transformPosition(\n {\n width: pageRect.size.width,\n height: pageRect.size.height,\n },\n {\n x: pageCoordinates.x,\n y: pageCoordinates.y,\n },\n rotation,\n scale,\n );\n\n return {\n x: scaledBasePosition.x + rotatedSize.x + this.viewportGap,\n y: scaledBasePosition.y + rotatedSize.y + this.viewportGap,\n };\n }\n\n return {\n x: scaledBasePosition.x + this.viewportGap,\n y: scaledBasePosition.y + this.viewportGap,\n };\n }\n\n getRectPositionForPage(\n pageNumber: number,\n virtualItems: VirtualItem[],\n scale: number,\n rotation: Rotation,\n rect: Rect,\n ): Rect | null {\n const totalContentSize = this.getTotalContentSize(virtualItems);\n const pageRect = this.getRectLocationForPage(pageNumber, virtualItems, totalContentSize);\n if (!pageRect) return null;\n\n const scaledBasePosition = scalePosition(pageRect.origin, scale);\n\n const rotatedSize = transformRect(\n {\n width: pageRect.size.width,\n height: pageRect.size.height,\n },\n rect,\n rotation,\n scale,\n );\n\n return {\n origin: {\n x: scaledBasePosition.x + rotatedSize.origin.x,\n y: scaledBasePosition.y + rotatedSize.origin.y,\n },\n size: rotatedSize.size,\n };\n }\n}\n","import { PdfPageObjectWithRotatedSize } from '@embedpdf/models';\nimport { ViewportMetrics } from '@embedpdf/plugin-viewport';\nimport { BaseScrollStrategy, ScrollStrategyConfig } from './base-strategy';\nimport { VirtualItem, PageLayout } from '../types/virtual-item';\nimport { ScrollMetrics } from '../types';\n\nexport class VerticalScrollStrategy extends BaseScrollStrategy {\n constructor(config: ScrollStrategyConfig) {\n super(config);\n }\n\n createVirtualItems(pdfPageObject: PdfPageObjectWithRotatedSize[][]): VirtualItem[] {\n let yOffset = 0;\n return pdfPageObject.map((pagesInSpread, index) => {\n let pageX = 0;\n const pageLayouts: PageLayout[] = pagesInSpread.map((page) => {\n const layout: PageLayout = {\n pageNumber: page.index + 1,\n pageIndex: page.index,\n x: pageX,\n y: 0,\n width: page.size.width,\n height: page.size.height,\n rotatedWidth: page.rotatedSize.width,\n rotatedHeight: page.rotatedSize.height,\n };\n pageX += page.rotatedSize.width + this.pageGap;\n return layout;\n });\n const width = pagesInSpread.reduce(\n (sum, page, i) =>\n sum + page.rotatedSize.width + (i < pagesInSpread.length - 1 ? this.pageGap : 0),\n 0,\n );\n const height = Math.max(...pagesInSpread.map((p) => p.rotatedSize.height));\n const item: VirtualItem = {\n id: `item-${index}`,\n x: 0,\n y: yOffset,\n offset: yOffset,\n width,\n height,\n pageLayouts,\n pageNumbers: pagesInSpread.map((p) => p.index + 1),\n index,\n };\n yOffset += height + this.pageGap;\n return item;\n });\n }\n\n getTotalContentSize(virtualItems: VirtualItem[]): { width: number; height: number } {\n if (virtualItems.length === 0) return { width: 0, height: 0 };\n const maxWidth = Math.max(...virtualItems.map((item) => item.width));\n const totalHeight =\n virtualItems[virtualItems.length - 1].y + virtualItems[virtualItems.length - 1].height;\n return {\n width: maxWidth,\n height: totalHeight,\n };\n }\n\n protected getScrollOffset(viewport: ViewportMetrics): number {\n return viewport.scrollTop;\n }\n\n protected getClientSize(viewport: ViewportMetrics): number {\n return viewport.clientHeight;\n }\n}\n","import { PdfPageObjectWithRotatedSize } from '@embedpdf/models';\nimport { ViewportMetrics } from '@embedpdf/plugin-viewport';\nimport { BaseScrollStrategy, ScrollStrategyConfig } from './base-strategy';\nimport { VirtualItem, PageLayout } from '../types/virtual-item';\n\nexport class HorizontalScrollStrategy extends BaseScrollStrategy {\n constructor(config: ScrollStrategyConfig) {\n super(config);\n }\n\n createVirtualItems(pdfPageObject: PdfPageObjectWithRotatedSize[][]): VirtualItem[] {\n let xOffset = 0;\n return pdfPageObject.map((pagesInSpread, index) => {\n let pageX = 0;\n const pageLayouts: PageLayout[] = pagesInSpread.map((page) => {\n const layout: PageLayout = {\n pageNumber: page.index + 1,\n pageIndex: page.index,\n x: pageX,\n y: 0,\n width: page.size.width,\n height: page.size.height,\n rotatedWidth: page.rotatedSize.width,\n rotatedHeight: page.rotatedSize.height,\n };\n pageX += page.rotatedSize.width + this.pageGap;\n return layout;\n });\n const width = pagesInSpread.reduce(\n (sum, page, i) =>\n sum + page.rotatedSize.width + (i < pagesInSpread.length - 1 ? this.pageGap : 0),\n 0,\n );\n const height = Math.max(...pagesInSpread.map((p) => p.rotatedSize.height));\n const item: VirtualItem = {\n id: `item-${index}`,\n x: xOffset,\n y: 0,\n offset: xOffset,\n width,\n height,\n pageLayouts,\n pageNumbers: pagesInSpread.map((p) => p.index + 1),\n index,\n };\n xOffset += width + this.pageGap;\n return item;\n });\n }\n\n getTotalContentSize(virtualItems: VirtualItem[]): { width: number; height: number } {\n if (virtualItems.length === 0) return { width: 0, height: 0 };\n const totalWidth =\n virtualItems[virtualItems.length - 1].x + virtualItems[virtualItems.length - 1].width;\n const maxHeight = Math.max(...virtualItems.map((item) => item.height));\n return {\n width: totalWidth,\n height: maxHeight,\n };\n }\n\n protected getScrollOffset(viewport: ViewportMetrics): number {\n return viewport.scrollLeft;\n }\n\n protected getClientSize(viewport: ViewportMetrics): number {\n return viewport.clientWidth;\n }\n}\n","import { Action } from '@embedpdf/core';\nimport { PageChangeState, ScrollState } from './types';\n\nexport const UPDATE_SCROLL_STATE = 'UPDATE_SCROLL_STATE';\nexport const SET_DESIRED_SCROLL_POSITION = 'SET_DESIRED_SCROLL_POSITION';\nexport const UPDATE_TOTAL_PAGES = 'UPDATE_TOTAL_PAGES';\nexport const SET_PAGE_CHANGE_STATE = 'SET_PAGE_CHANGE_STATE';\n\nexport interface UpdateScrollStateAction extends Action {\n type: typeof UPDATE_SCROLL_STATE;\n payload: Partial<ScrollState>;\n}\n\nexport interface SetDesiredScrollPositionAction extends Action {\n type: typeof SET_DESIRED_SCROLL_POSITION;\n payload: { x: number; y: number };\n}\n\nexport interface UpdateTotalPagesAction extends Action {\n type: typeof UPDATE_TOTAL_PAGES;\n payload: number;\n}\n\nexport interface SetPageChangeStateAction extends Action {\n type: typeof SET_PAGE_CHANGE_STATE;\n payload: PageChangeState;\n}\n\nexport type ScrollAction =\n | UpdateScrollStateAction\n | SetDesiredScrollPositionAction\n | UpdateTotalPagesAction\n | SetPageChangeStateAction;\n\nexport function updateScrollState(payload: Partial<ScrollState>): UpdateScrollStateAction {\n return { type: UPDATE_SCROLL_STATE, payload };\n}\n\nexport function setDesiredScrollPosition(payload: {\n x: number;\n y: number;\n}): SetDesiredScrollPositionAction {\n return { type: SET_DESIRED_SCROLL_POSITION, payload };\n}\n\nexport function updateTotalPages(payload: number): UpdateTotalPagesAction {\n return { type: UPDATE_TOTAL_PAGES, payload };\n}\n\nexport function setPageChangeState(payload: PageChangeState): SetPageChangeStateAction {\n return { type: SET_PAGE_CHANGE_STATE, payload };\n}\n","import { ScrollerLayout, ScrollState } from './types';\n\nexport const getScrollerLayout = (state: ScrollState, scale: number): ScrollerLayout => {\n return {\n startSpacing: state.startSpacing,\n endSpacing: state.endSpacing,\n totalWidth: state.totalContentSize.width * scale,\n totalHeight: state.totalContentSize.height * scale,\n pageGap: state.pageGap * scale,\n strategy: state.strategy,\n items: state.renderedPageIndexes.map((idx) => {\n return {\n ...state.virtualItems[idx],\n pageLayouts: state.virtualItems[idx].pageLayouts.map((layout) => {\n return {\n ...layout,\n rotatedWidth: layout.rotatedWidth * scale,\n rotatedHeight: layout.rotatedHeight * scale,\n width: layout.width * scale,\n height: layout.height * scale,\n };\n }),\n };\n }),\n };\n};\n","import {\n BasePlugin,\n CoreState,\n PluginRegistry,\n SET_DOCUMENT,\n SET_PAGES,\n SET_ROTATION,\n StoreState,\n Unsubscribe,\n createBehaviorEmitter,\n getPagesWithRotatedSize,\n} from '@embedpdf/core';\nimport { PdfPageObjectWithRotatedSize, Rect, Rotation } from '@embedpdf/models';\nimport { ViewportCapability, ViewportMetrics, ViewportPlugin } from '@embedpdf/plugin-viewport';\nimport {\n ScrollCapability,\n ScrollPluginConfig,\n ScrollStrategy,\n ScrollMetrics,\n ScrollState,\n LayoutChangePayload,\n ScrollerLayout,\n ScrollToPageOptions,\n PageChangePayload,\n ScrollBehavior,\n PageChangeState,\n} from './types';\nimport { BaseScrollStrategy, ScrollStrategyConfig } from './strategies/base-strategy';\nimport { VerticalScrollStrategy } from './strategies/vertical-strategy';\nimport { HorizontalScrollStrategy } from './strategies/horizontal-strategy';\nimport { updateScrollState, ScrollAction, updateTotalPages, setPageChangeState } from './actions';\nimport { VirtualItem } from './types/virtual-item';\nimport { getScrollerLayout } from './selectors';\n\ntype PartialScroll = Partial<ScrollState>;\ntype Emits = {\n layout?: LayoutChangePayload;\n metrics?: ScrollMetrics;\n};\n\nexport class ScrollPlugin extends BasePlugin<\n ScrollPluginConfig,\n ScrollCapability,\n ScrollState,\n ScrollAction\n> {\n static readonly id = 'scroll' as const;\n private viewport: ViewportCapability;\n private strategy: BaseScrollStrategy;\n private strategyConfig: ScrollStrategyConfig;\n private currentScale: number = 1;\n private currentRotation: Rotation = Rotation.Degree0;\n private initialPage?: number;\n private currentPage: number = 1;\n private layoutReady: boolean = false;\n\n private readonly pageChangeState$ = createBehaviorEmitter<PageChangeState>();\n private readonly layout$ = createBehaviorEmitter<LayoutChangePayload>();\n private readonly scroll$ = createBehaviorEmitter<ScrollMetrics>();\n private readonly state$ = createBehaviorEmitter<ScrollState>();\n private readonly scrollerLayout$ = createBehaviorEmitter<ScrollerLayout>();\n private readonly pageChange$ = createBehaviorEmitter<PageChangePayload>();\n private readonly layoutReady$ = createBehaviorEmitter<boolean>();\n\n constructor(\n public readonly id: string,\n registry: PluginRegistry,\n private config?: ScrollPluginConfig,\n ) {\n super(id, registry);\n\n this.viewport = this.registry.getPlugin<ViewportPlugin>('viewport')!.provides();\n\n this.strategyConfig = {\n pageGap: this.config?.pageGap ?? 10,\n viewportGap: this.viewport.getViewportGap(),\n bufferSize: this.config?.bufferSize ?? 2,\n };\n\n this.strategy =\n this.config?.strategy === ScrollStrategy.Horizontal\n ? new HorizontalScrollStrategy(this.strategyConfig)\n : new VerticalScrollStrategy(this.strategyConfig);\n\n this.initialPage = this.config?.initialPage;\n this.currentScale = this.coreState.core.scale;\n this.currentRotation = this.coreState.core.rotation;\n // Subscribe to viewport scroll activity to detect when smooth scrolling ends\n this.viewport.onScrollActivity((activity) => {\n if (this.state.pageChangeState.isChanging && !activity.isSmoothScrolling) {\n // Smooth scrolling has ended\n this.completePageChange();\n }\n });\n // Subscribe to viewport and page manager events\n this.viewport.onViewportChange((vp) => this.commitMetrics(this.computeMetrics(vp)), {\n mode: 'throttle',\n wait: 100,\n });\n this.coreStore.onAction(SET_DOCUMENT, (_action, state) => {\n const totalPages = state.core.pages.length;\n this.dispatch(updateTotalPages(totalPages));\n this.pageChange$.emit({ pageNumber: this.currentPage, totalPages });\n this.refreshAll(getPagesWithRotatedSize(state.core), this.viewport.getMetrics());\n });\n this.coreStore.onAction(SET_ROTATION, (_action, state) =>\n this.refreshAll(getPagesWithRotatedSize(state.core), this.viewport.getMetrics()),\n );\n this.coreStore.onAction(SET_PAGES, (_action, state) =>\n this.refreshAll(getPagesWithRotatedSize(state.core), this.viewport.getMetrics()),\n );\n }\n\n private startPageChange(targetPage: number, behavior: ScrollBehavior = 'smooth') {\n const pageChangeState: PageChangeState = {\n isChanging: true,\n targetPage,\n fromPage: this.currentPage,\n startTime: Date.now(),\n };\n\n this.dispatch(setPageChangeState(pageChangeState));\n\n // For instant behavior, complete immediately\n if (behavior === 'instant') {\n // Use setTimeout to ensure the scroll happens first\n this.completePageChange();\n }\n }\n\n private completePageChange() {\n if (!this.state.pageChangeState.isChanging) return;\n\n const pageChangeState: PageChangeState = {\n isChanging: false,\n targetPage: this.state.pageChangeState.targetPage,\n fromPage: this.state.pageChangeState.fromPage,\n startTime: this.state.pageChangeState.startTime,\n };\n\n this.dispatch(setPageChangeState(pageChangeState));\n }\n\n /* ------------------------------------------------------------------ */\n /* ᴄᴏᴍᴘᴜᴛᴇʀs */\n /* ------------------------------------------------------------------ */\n\n private computeLayout(pages: PdfPageObjectWithRotatedSize[][]) {\n const virtualItems = this.strategy.createVirtualItems(pages);\n const totalContentSize = this.strategy.getTotalContentSize(virtualItems);\n return { virtualItems, totalContentSize };\n }\n\n private computeMetrics(vp: ViewportMetrics, items: VirtualItem[] = this.state.virtualItems) {\n return this.strategy.handleScroll(vp, items, this.currentScale);\n }\n\n /* ------------------------------------------------------------------ */\n /* ᴄᴏᴍᴍɪᴛ (single source of truth) */\n /* ------------------------------------------------------------------ */\n\n private commit(stateDelta: PartialScroll, emit?: Emits) {\n /* update Redux-like store */\n this.dispatch(updateScrollState(stateDelta));\n\n /* fire optional events */\n if (emit?.layout) this.layout$.emit(emit.layout);\n if (emit?.metrics) {\n this.scroll$.emit(emit.metrics);\n\n if (emit.metrics.currentPage !== this.currentPage) {\n this.currentPage = emit.metrics.currentPage;\n this.pageChange$.emit({ pageNumber: this.currentPage, totalPages: this.state.totalPages });\n }\n }\n\n /* keep scroller-layout reactive */\n this.scrollerLayout$.emit(this.getScrollerLayout());\n }\n\n /* convenience wrappers */\n private commitMetrics(metrics: ScrollMetrics) {\n this.commit(metrics, { metrics });\n }\n\n /* full re-compute after page-spread or initialisation */\n private refreshAll(pages: PdfPageObjectWithRotatedSize[][], vp: ViewportMetrics) {\n const layout = this.computeLayout(pages);\n const metrics = this.computeMetrics(vp, layout.virtualItems);\n\n this.commit({ ...layout, ...metrics }, { layout, metrics });\n }\n\n private getVirtualItemsFromState(): VirtualItem[] {\n return this.state.virtualItems || [];\n }\n\n public onScrollerData(callback: (layout: ScrollerLayout) => void): Unsubscribe {\n return this.scrollerLayout$.on(callback);\n }\n\n public getScrollerLayout(): ScrollerLayout {\n const scale = this.coreState.core.scale;\n return getScrollerLayout(this.state, scale);\n }\n\n private pushScrollLayout() {\n this.scrollerLayout$.emit(this.getScrollerLayout());\n }\n\n override onStoreUpdated(prevState: ScrollState, newState: ScrollState): void {\n this.pushScrollLayout();\n\n if (prevState.pageChangeState !== newState.pageChangeState) {\n this.pageChangeState$.emit(newState.pageChangeState);\n }\n }\n\n override onCoreStoreUpdated(\n prevState: StoreState<CoreState>,\n newState: StoreState<CoreState>,\n ): void {\n if (prevState.core.scale !== newState.core.scale) {\n this.currentScale = newState.core.scale;\n this.commitMetrics(this.computeMetrics(this.viewport.getMetrics()));\n }\n if (prevState.core.rotation !== newState.core.rotation) {\n this.currentRotation = newState.core.rotation;\n }\n }\n\n /**\n * Change the scroll strategy at runtime (e.g., vertical <-> horizontal)\n * @param newStrategy ScrollStrategy.Horizontal or ScrollStrategy.Vertical\n */\n private setScrollStrategy(newStrategy: ScrollStrategy) {\n // Only update if the strategy is actually changing\n if (\n (newStrategy === ScrollStrategy.Horizontal &&\n this.strategy instanceof HorizontalScrollStrategy) ||\n (newStrategy === ScrollStrategy.Vertical && this.strategy instanceof VerticalScrollStrategy)\n ) {\n return;\n }\n\n this.strategy =\n newStrategy === ScrollStrategy.Horizontal\n ? new HorizontalScrollStrategy(this.strategyConfig)\n : new VerticalScrollStrategy(this.strategyConfig);\n\n // Update state with new strategy\n this.dispatch(\n updateScrollState({\n strategy: newStrategy,\n }),\n );\n\n // Recalculate layout and scroll metrics\n const pages = getPagesWithRotatedSize(this.coreState.core);\n this.refreshAll(pages, this.viewport.getMetrics());\n }\n\n public setLayoutReady() {\n if (this.layoutReady) return;\n\n this.layoutReady = true;\n this.layoutReady$.emit(true);\n\n if (this.initialPage) {\n this.scrollToPage({ pageNumber: this.initialPage, behavior: 'instant' });\n }\n }\n\n protected buildCapability(): ScrollCapability {\n return {\n onStateChange: this.state$.on,\n onLayoutChange: this.layout$.on,\n onScroll: this.scroll$.on,\n onPageChange: this.pageChange$.on,\n onLayoutReady: this.layoutReady$.on,\n onPageChangeState: this.pageChangeState$.on,\n getCurrentPage: () => this.currentPage,\n getTotalPages: () => this.state.totalPages,\n getPageChangeState: () => this.state.pageChangeState,\n scrollToPage: this.scrollToPage.bind(this),\n scrollToNextPage: this.scrollToNextPage.bind(this),\n scrollToPreviousPage: this.scrollToPreviousPage.bind(this),\n getMetrics: this.getMetrics.bind(this),\n getLayout: this.getLayout.bind(this),\n getRectPositionForPage: this.getRectPositionForPage.bind(this),\n getPageGap: () => this.state.pageGap,\n setScrollStrategy: (strategy: ScrollStrategy) => this.setScrollStrategy(strategy),\n };\n }\n\n private scrollToPage(options: ScrollToPageOptions) {\n const { pageNumber, behavior = 'smooth', pageCoordinates, center = false } = options;\n this.startPageChange(pageNumber, behavior);\n const virtualItems = this.getVirtualItemsFromState();\n const position = this.strategy.getScrollPositionForPage(\n pageNumber,\n virtualItems,\n this.currentScale,\n this.currentRotation,\n pageCoordinates,\n );\n if (position) {\n this.viewport.scrollTo({ ...position, behavior, center });\n } else {\n // If we couldn't find the position, complete the page change immediately\n this.completePageChange();\n }\n }\n\n private scrollToNextPage(behavior: ScrollBehavior = 'smooth') {\n const virtualItems = this.getVirtualItemsFromState();\n const currentItemIndex = virtualItems.findIndex((item) =>\n item.pageNumbers.includes(this.currentPage),\n );\n if (currentItemIndex >= 0 && currentItemIndex < virtualItems.length - 1) {\n const nextItem = virtualItems[currentItemIndex + 1];\n const targetPage = nextItem.pageNumbers[0];\n this.startPageChange(targetPage, behavior);\n\n const position = this.strategy.getScrollPositionForPage(\n nextItem.pageNumbers[0],\n virtualItems,\n this.currentScale,\n this.currentRotation,\n );\n if (position) {\n this.viewport.scrollTo({ ...position, behavior });\n } else {\n // If we couldn't find the position, complete the page change immediately\n this.completePageChange();\n }\n }\n }\n\n private scrollToPreviousPage(behavior: ScrollBehavior = 'smooth') {\n const virtualItems = this.getVirtualItemsFromState();\n const currentItemIndex = virtualItems.findIndex((item) =>\n item.pageNumbers.includes(this.currentPage),\n );\n if (currentItemIndex > 0) {\n const prevItem = virtualItems[currentItemIndex - 1];\n const targetPage = prevItem.pageNumbers[0];\n this.startPageChange(targetPage, behavior);\n\n const position = this.strategy.getScrollPositionForPage(\n prevItem.pageNumbers[0],\n virtualItems,\n this.currentScale,\n this.currentRotation,\n );\n if (position) {\n this.viewport.scrollTo({ ...position, behavior });\n } else {\n // If we couldn't find the position, complete the page change immediately\n this.completePageChange();\n }\n }\n }\n\n private getMetrics(viewport?: ViewportMetrics): ScrollMetrics {\n const metrics = viewport || this.viewport.getMetrics();\n const virtualItems = this.getVirtualItemsFromState();\n return this.strategy.handleScroll(metrics, virtualItems, this.currentScale);\n }\n\n private getLayout(): LayoutChangePayload {\n return {\n virtualItems: this.state.virtualItems,\n totalContentSize: this.state.totalContentSize,\n };\n }\n\n private getRectPositionForPage(\n pageIndex: number,\n rect: Rect,\n scale?: number,\n rotation?: Rotation,\n ): Rect | null {\n return this.strategy.getRectPositionForPage(\n pageIndex + 1,\n this.state.virtualItems,\n scale ?? this.currentScale,\n rotation ?? this.currentRotation,\n rect,\n );\n }\n\n async initialize(): Promise<void> {\n // No DOM initialization needed; state drives rendering\n }\n\n async destroy(): Promise<void> {\n this.layout$.clear();\n this.scroll$.clear();\n this.pageChange$.clear();\n this.state$.clear();\n this.scrollerLayout$.clear();\n this.layoutReady$.clear();\n this.pageChangeState$.clear();\n super.destroy();\n }\n}\n","import { PluginManifest } from '@embedpdf/core';\nimport { ScrollPluginConfig } from './types';\n\nexport const SCROLL_PLUGIN_ID = 'scroll';\n\nexport const manifest: PluginManifest<ScrollPluginConfig> = {\n id: SCROLL_PLUGIN_ID,\n name: 'Scroll Plugin',\n version: '1.0.0',\n provides: ['scroll'],\n requires: ['viewport'],\n optional: [],\n defaultConfig: {\n enabled: true,\n pageGap: 10,\n },\n};\n","import { Reducer, CoreState, SET_SCALE, SetScaleAction } from '@embedpdf/core';\nimport {\n ScrollState,\n ScrollStrategy,\n ScrollPluginConfig,\n ScrollMetrics,\n PageChangeState,\n} from './types';\nimport {\n ScrollAction,\n UPDATE_SCROLL_STATE,\n SET_DESIRED_SCROLL_POSITION,\n UPDATE_TOTAL_PAGES,\n SET_PAGE_CHANGE_STATE,\n} from './actions';\n\nexport const defaultScrollMetrics: ScrollMetrics = {\n currentPage: 1,\n visiblePages: [],\n pageVisibilityMetrics: [],\n renderedPageIndexes: [],\n scrollOffset: { x: 0, y: 0 },\n startSpacing: 0,\n endSpacing: 0,\n};\n\nexport const defaultPageChangeState: PageChangeState = {\n isChanging: false,\n targetPage: 1,\n fromPage: 1,\n startTime: 0,\n};\n\nexport const initialState: (coreState: CoreState, config: ScrollPluginConfig) => ScrollState = (\n coreState,\n config,\n) => ({\n virtualItems: [],\n totalPages: coreState.pages.length,\n totalContentSize: { width: 0, height: 0 },\n desiredScrollPosition: { x: 0, y: 0 },\n strategy: config.strategy ?? ScrollStrategy.Vertical,\n pageGap: config.pageGap ?? 10,\n scale: coreState.scale,\n pageChangeState: defaultPageChangeState,\n ...defaultScrollMetrics,\n});\n\nexport const scrollReducer: Reducer<ScrollState, ScrollAction | SetScaleAction> = (\n state,\n action,\n) => {\n switch (action.type) {\n case UPDATE_TOTAL_PAGES:\n return { ...state, totalPages: action.payload };\n case SET_SCALE:\n return { ...state, scale: action.payload };\n case UPDATE_SCROLL_STATE:\n return { ...state, ...action.payload };\n case SET_DESIRED_SCROLL_POSITION:\n return { ...state, desiredScrollPosition: action.payload };\n case SET_PAGE_CHANGE_STATE:\n return { ...state, pageChangeState: action.payload };\n default:\n return state;\n }\n};\n","import { PluginPackage } from '@embedpdf/core';\nimport { ScrollPlugin } from './scroll-plugin';\nimport { manifest, SCROLL_PLUGIN_ID } from './manifest';\nimport { ScrollPluginConfig, ScrollState } from './types';\nimport { scrollReducer, initialState } from './reducer';\nimport { ScrollAction } from './actions';\n\nexport const ScrollPluginPackage: PluginPackage<\n ScrollPlugin,\n ScrollPluginConfig,\n ScrollState,\n ScrollAction\n> = {\n manifest,\n create: (registry, config) => new ScrollPlugin(SCROLL_PLUGIN_ID, registry, config),\n reducer: scrollReducer,\n initialState: (coreState, config) => initialState(coreState, config),\n};\n\nexport * from './scroll-plugin';\nexport * from './types';\nexport * from './manifest';\nexport * from './types/virtual-item';\n"],"names":["ScrollStrategy","item"],"mappings":";;AAmCY,IAAA,mCAAAA,oBAAL;AACLA,kBAAA,UAAW,IAAA;AACXA,kBAAA,YAAa,IAAA;AAFHA,SAAAA;AAAA,GAAA,kBAAA,CAAA,CAAA;ACfL,MAAe,mBAAmB;AAAA,EAKvC,YAAY,QAA8B;AACnC,SAAA,UAAU,OAAO,WAAW;AAC5B,SAAA,cAAc,OAAO,eAAe;AACpC,SAAA,aAAa,OAAO,cAAc;AAAA,EAAA;AAAA,EAQ/B,gBACR,UACA,cACA,OACgC;AAC1B,UAAA,eAAe,KAAK,gBAAgB,QAAQ;AAC5C,UAAA,aAAa,KAAK,cAAc,QAAQ;AAC9C,UAAM,gBAAgB;AACtB,UAAM,cAAc,eAAe;AAEnC,QAAI,aAAa;AACjB,WACE,aAAa,aAAa,WACzB,aAAa,UAAU,EAAE,SAAS,aAAa,UAAU,EAAE,UAAU,SAAS,eAC/E;AACA;AAAA,IAAA;AAGF,QAAI,WAAW;AACR,WAAA,WAAW,aAAa,UAAU,aAAa,QAAQ,EAAE,SAAS,SAAS,aAAa;AAC7F;AAAA,IAAA;AAGK,WAAA;AAAA,MACL,OAAO,KAAK,IAAI,GAAG,aAAa,KAAK,UAAU;AAAA,MAC/C,KAAK,KAAK,IAAI,aAAa,SAAS,GAAG,WAAW,KAAK,aAAa,CAAC;AAAA,IACvE;AAAA,EAAA;AAAA,EAGF,aACE,UACA,cACA,OACe;AACf,UAAM,QAAQ,KAAK,gBAAgB,UAAU,cAAc,KAAK;AAChE,UAAM,eAAe,aAAa,MAAM,MAAM,OAAO,MAAM,MAAM,CAAC;AAClE,UAAM,wBAAwB,KAAK,wBAAwB,cAAc,UAAU,KAAK;AACxF,UAAM,eAAe,sBAAsB,IAAI,CAAC,MAAM,EAAE,UAAU;AAClE,UAAM,sBAAsB,aACzB,MAAM,MAAM,OAAO,MAAM,MAAM,CAAC,EAChC,QAAQ,CAAC,SAAS,KAAK,KAAK;AACzB,UAAA,cAAc,KAAK,qBAAqB,qBAAqB;AAC7D,UAAA,QAAQ,aAAa,MAAM,KAAK;AAChC,UAAA,OAAO,aAAa,MAAM,GAAG;AACnC,UAAM,eAAe,QAAQ,MAAM,SAAS,QAAQ;AACpD,UAAM,aAAa,QACd,aAAa,aAAa,SAAS,CAAC,EAAE;AAAA,IACrC,aAAa,aAAa,SAAS,CAAC,EAAE,UACtC;AAAA,KACD,KAAK,SAAS,KAAK,UAAU,QAC9B;AAEG,WAAA;AAAA,MACL;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA,cAAc,EAAE,GAAG,SAAS,YAAY,GAAG,SAAS,UAAU;AAAA,MAC9D;AAAA,MACA;AAAA,IACF;AAAA,EAAA;AAAA,EAGQ,wBACR,cACA,UACA,OACwC;AACxC,UAAM,oBAA4D,CAAC;AAEtD,iBAAA,QAAQ,CAAC,SAAS;AACxB,WAAA,YAAY,QAAQ,CAAC,SAAS;AAC3B,cAAA,QAAQ,KAAK,IAAI;AACjB,cAAA,QAAQ,KAAK,IAAI;AACjB,cAAA,QAAQ,QAAQ,KAAK,IAAI;AACzB,cAAA,QAAQ,QAAQ,KAAK,IAAI;AACzB,cAAA,YAAY,KAAK,eAAe;AAChC,cAAA,aAAa,KAAK,gBAAgB;AAExC,cAAM,eAAe,SAAS;AAC9B,cAAM,cAAc,SAAS;AACvB,cAAA,gBAAgB,eAAe,SAAS;AACxC,cAAA,iBAAiB,cAAc,SAAS;AAE9C,cAAM,mBAAmB,KAAK,IAAI,OAAO,YAAY;AACrD,cAAM,kBAAkB,KAAK,IAAI,OAAO,WAAW;AACnD,cAAM,oBAAoB,KAAK,IAAI,QAAQ,WAAW,aAAa;AACnE,cAAM,qBAAqB,KAAK,IAAI,QAAQ,YAAY,cAAc;AAElE,YAAA,mBAAmB,qBAAqB,kBAAkB,oBAAoB;AAChF,gBAAM,eAAe,oBAAoB;AACzC,gBAAM,gBAAgB,qBAAqB;AAC3C,gBAAM,YAAY,YAAY;AAC9B,gBAAM,cAAc,eAAe;AAEnC,4BAAkB,KAAK;AAAA,YACrB,YAAY,KAAK;AAAA,YACjB,WAAW,mBAAmB;AAAA,YAC9B,WAAW,kBAAkB;AAAA,YAC7B,mBAAoB,cAAc,YAAa;AAAA,YAC/C,UAAU;AAAA,cACR,QAAQ,mBAAmB,SAAS;AAAA,cACpC,QAAQ,kBAAkB,SAAS;AAAA,cACnC,cAAc,eAAe;AAAA,cAC7B,eAAe,gBAAgB;AAAA,cAC/B,OAAO;AAAA,YACT;AAAA,YACA,QAAQ;AAAA,cACN,OAAO,mBAAmB;AAAA,cAC1B,OAAO,kBAAkB;AAAA,cACzB;AAAA,cACA;AAAA,cACA;AAAA,YAAA;AAAA,UACF,CACD;AAAA,QAAA;AAAA,MACH,CACD;AAAA,IAAA,CACF;AAEM,WAAA;AAAA,EAAA;AAAA,EAGC,qBACR,mBACQ;AACJ,QAAA,kBAAkB,WAAW,EAAU,QAAA;AAErC,UAAA,gBAAgB,KAAK,IAAI,GAAG,kBAAkB,IAAI,CAAC,MAAM,EAAE,iBAAiB,CAAC;AACnF,UAAM,mBAAmB,kBAAkB,OAAO,CAAC,MAAM,EAAE,sBAAsB,aAAa;AAE9F,WAAO,iBAAiB,WAAW,IAC/B,iBAAiB,CAAC,EAAE,aACpB,iBAAiB,KAAK,CAAC,GAAG,MAAM,EAAE,aAAa,EAAE,UAAU,EAAE,CAAC,EAAE;AAAA,EAAA;AAAA,EAG9D,uBACN,YACA,cACA,kBACa;AAEP,UAAA,OAAO,aAAa,KAAK,CAACC,UAASA,MAAK,YAAY,SAAS,UAAU,CAAC;AAC1E,QAAA,CAAC,KAAa,QAAA;AAGZ,UAAA,aAAa,KAAK,YAAY,KAAK,CAAC,WAAW,OAAO,eAAe,UAAU;AACjF,QAAA,CAAC,WAAmB,QAAA;AAGxB,QAAI,mBAAmB;AACvB,QAAI,kBAAkB;AACpB,YAAM,WAAW,iBAAiB;AAC9B,UAAA,KAAK,QAAQ,UAAU;AACL,4BAAA,WAAW,KAAK,SAAS;AAAA,MAAA;AAAA,IAC/C;AAGK,WAAA;AAAA,MACL,QAAQ;AAAA,QACN,GAAG,KAAK,IAAI,WAAW,IAAI;AAAA,QAC3B,GAAG,KAAK,IAAI,WAAW;AAAA,MACzB;AAAA,MACA,MAAM;AAAA,QACJ,OAAO,WAAW;AAAA,QAClB,QAAQ,WAAW;AAAA,MAAA;AAAA,IAEvB;AAAA,EAAA;AAAA,EAGF,yBACE,YACA,cACA,OACA,UACA,iBACiB;AACX,UAAA,mBAAmB,KAAK,oBAAoB,YAAY;AAC9D,UAAM,WAAW,KAAK,uBAAuB,YAAY,cAAc,gBAAgB;AACnF,QAAA,CAAC,SAAiB,QAAA;AAEtB,UAAM,qBAAqB,cAAc,SAAS,QAAQ,KAAK;AAG/D,QAAI,iBAAiB;AACnB,YAAM,cAAc;AAAA,QAClB;AAAA,UACE,OAAO,SAAS,KAAK;AAAA,UACrB,QAAQ,SAAS,KAAK;AAAA,QACxB;AAAA,QACA;AAAA,UACE,GAAG,gBAAgB;AAAA,UACnB,GAAG,gBAAgB;AAAA,QACrB;AAAA,QACA;AAAA,QACA;AAAA,MACF;AAEO,aAAA;AAAA,QACL,GAAG,mBAAmB,IAAI,YAAY,IAAI,KAAK;AAAA,QAC/C,GAAG,mBAAmB,IAAI,YAAY,IAAI,KAAK;AAAA,MACjD;AAAA,IAAA;AAGK,WAAA;AAAA,MACL,GAAG,mBAAmB,IAAI,KAAK;AAAA,MAC/B,GAAG,mBAAmB,IAAI,KAAK;AAAA,IACjC;AAAA,EAAA;AAAA,EAGF,uBACE,YACA,cACA,OACA,UACA,MACa;AACP,UAAA,mBAAmB,KAAK,oBAAoB,YAAY;AAC9D,UAAM,WAAW,KAAK,uBAAuB,YAAY,cAAc,gBAAgB;AACnF,QAAA,CAAC,SAAiB,QAAA;AAEtB,UAAM,qBAAqB,cAAc,SAAS,QAAQ,KAAK;AAE/D,UAAM,cAAc;AAAA,MAClB;AAAA,QACE,OAAO,SAAS,KAAK;AAAA,QACrB,QAAQ,SAAS,KAAK;AAAA,MACxB;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAEO,WAAA;AAAA,MACL,QAAQ;AAAA,QACN,GAAG,mBAAmB,IAAI,YAAY,OAAO;AAAA,QAC7C,GAAG,mBAAmB,IAAI,YAAY,OAAO;AAAA,MAC/C;AAAA,MACA,MAAM,YAAY;AAAA,IACpB;AAAA,EAAA;AAEJ;AC9QO,MAAM,+BAA+B,mBAAmB;AAAA,EAC7D,YAAY,QAA8B;AACxC,UAAM,MAAM;AAAA,EAAA;AAAA,EAGd,mBAAmB,eAAgE;AACjF,QAAI,UAAU;AACd,WAAO,cAAc,IAAI,CAAC,eAAe,UAAU;AACjD,UAAI,QAAQ;AACZ,YAAM,cAA4B,cAAc,IAAI,CAAC,SAAS;AAC5D,cAAM,SAAqB;AAAA,UACzB,YAAY,KAAK,QAAQ;AAAA,UACzB,WAAW,KAAK;AAAA,UAChB,GAAG;AAAA,UACH,GAAG;AAAA,UACH,OAAO,KAAK,KAAK;AAAA,UACjB,QAAQ,KAAK,KAAK;AAAA,UAClB,cAAc,KAAK,YAAY;AAAA,UAC/B,eAAe,KAAK,YAAY;AAAA,QAClC;AACS,iBAAA,KAAK,YAAY,QAAQ,KAAK;AAChC,eAAA;AAAA,MAAA,CACR;AACD,YAAM,QAAQ,cAAc;AAAA,QAC1B,CAAC,KAAK,MAAM,MACV,MAAM,KAAK,YAAY,SAAS,IAAI,cAAc,SAAS,IAAI,KAAK,UAAU;AAAA,QAChF;AAAA,MACF;AACM,YAAA,SAAS,KAAK,IAAI,GAAG,cAAc,IAAI,CAAC,MAAM,EAAE,YAAY,MAAM,CAAC;AACzE,YAAM,OAAoB;AAAA,QACxB,IAAI,QAAQ,KAAK;AAAA,QACjB,GAAG;AAAA,QACH,GAAG;AAAA,QACH,QAAQ;AAAA,QACR;AAAA,QACA;AAAA,QACA;AAAA,QACA,aAAa,cAAc,IAAI,CAAC,MAAM,EAAE,QAAQ,CAAC;AAAA,QACjD;AAAA,MACF;AACA,iBAAW,SAAS,KAAK;AAClB,aAAA;AAAA,IAAA,CACR;AAAA,EAAA;AAAA,EAGH,oBAAoB,cAAgE;AAC9E,QAAA,aAAa,WAAW,EAAG,QAAO,EAAE,OAAO,GAAG,QAAQ,EAAE;AACtD,UAAA,WAAW,KAAK,IAAI,GAAG,aAAa,IAAI,CAAC,SAAS,KAAK,KAAK,CAAC;AAC7D,UAAA,cACJ,aAAa,aAAa,SAAS,CAAC,EAAE,IAAI,aAAa,aAAa,SAAS,CAAC,EAAE;AAC3E,WAAA;AAAA,MACL,OAAO;AAAA,MACP,QAAQ;AAAA,IACV;AAAA,EAAA;AAAA,EAGQ,gBAAgB,UAAmC;AAC3D,WAAO,SAAS;AAAA,EAAA;AAAA,EAGR,cAAc,UAAmC;AACzD,WAAO,SAAS;AAAA,EAAA;AAEpB;AChEO,MAAM,iCAAiC,mBAAmB;AAAA,EAC/D,YAAY,QAA8B;AACxC,UAAM,MAAM;AAAA,EAAA;AAAA,EAGd,mBAAmB,eAAgE;AACjF,QAAI,UAAU;AACd,WAAO,cAAc,IAAI,CAAC,eAAe,UAAU;AACjD,UAAI,QAAQ;AACZ,YAAM,cAA4B,cAAc,IAAI,CAAC,SAAS;AAC5D,cAAM,SAAqB;AAAA,UACzB,YAAY,KAAK,QAAQ;AAAA,UACzB,WAAW,KAAK;AAAA,UAChB,GAAG;AAAA,UACH,GAAG;AAAA,UACH,OAAO,KAAK,KAAK;AAAA,UACjB,QAAQ,KAAK,KAAK;AAAA,UAClB,cAAc,KAAK,YAAY;AAAA,UAC/B,eAAe,KAAK,YAAY;AAAA,QAClC;AACS,iBAAA,KAAK,YAAY,QAAQ,KAAK;AAChC,eAAA;AAAA,MAAA,CACR;AACD,YAAM,QAAQ,cAAc;AAAA,QAC1B,CAAC,KAAK,MAAM,MACV,MAAM,KAAK,YAAY,SAAS,IAAI,cAAc,SAAS,IAAI,KAAK,UAAU;AAAA,QAChF;AAAA,MACF;AACM,YAAA,SAAS,KAAK,IAAI,GAAG,cAAc,IAAI,CAAC,MAAM,EAAE,YAAY,MAAM,CAAC;AACzE,YAAM,OAAoB;AAAA,QACxB,IAAI,QAAQ,KAAK;AAAA,QACjB,GAAG;AAAA,QACH,GAAG;AAAA,QACH,QAAQ;AAAA,QACR;AAAA,QACA;AAAA,QACA;AAAA,QACA,aAAa,cAAc,IAAI,CAAC,MAAM,EAAE,QAAQ,CAAC;AAAA,QACjD;AAAA,MACF;AACA,iBAAW,QAAQ,KAAK;AACjB,aAAA;AAAA,IAAA,CACR;AAAA,EAAA;AAAA,EAGH,oBAAoB,cAAgE;AAC9E,QAAA,aAAa,WAAW,EAAG,QAAO,EAAE,OAAO,GAAG,QAAQ,EAAE;AACtD,UAAA,aACJ,aAAa,aAAa,SAAS,CAAC,EAAE,IAAI,aAAa,aAAa,SAAS,CAAC,EAAE;AAC5E,UAAA,YAAY,KAAK,IAAI,GAAG,aAAa,IAAI,CAAC,SAAS,KAAK,MAAM,CAAC;AAC9D,WAAA;AAAA,MACL,OAAO;AAAA,MACP,QAAQ;AAAA,IACV;AAAA,EAAA;AAAA,EAGQ,gBAAgB,UAAmC;AAC3D,WAAO,SAAS;AAAA,EAAA;AAAA,EAGR,cAAc,UAAmC;AACzD,WAAO,SAAS;AAAA,EAAA;AAEpB;ACjEO,MAAM,sBAAsB;AAC5B,MAAM,8BAA8B;AACpC,MAAM,qBAAqB;AAC3B,MAAM,wBAAwB;AA4B9B,SAAS,kBAAkB,SAAwD;AACjF,SAAA,EAAE,MAAM,qBAAqB,QAAQ;AAC9C;AASO,SAAS,iBAAiB,SAAyC;AACjE,SAAA,EAAE,MAAM,oBAAoB,QAAQ;AAC7C;AAEO,SAAS,mBAAmB,SAAoD;AAC9E,SAAA,EAAE,MAAM,uBAAuB,QAAQ;AAChD;ACjDa,MAAA,oBAAoB,CAAC,OAAoB,UAAkC;AAC/E,SAAA;AAAA,IACL,cAAc,MAAM;AAAA,IACpB,YAAY,MAAM;AAAA,IAClB,YAAY,MAAM,iBAAiB,QAAQ;AAAA,IAC3C,aAAa,MAAM,iBAAiB,SAAS;AAAA,IAC7C,SAAS,MAAM,UAAU;AAAA,IACzB,UAAU,MAAM;AAAA,IAChB,OAAO,MAAM,oBAAoB,IAAI,CAAC,QAAQ;AACrC,aAAA;AAAA,QACL,GAAG,MAAM,aAAa,GAAG;AAAA,QACzB,aAAa,MAAM,aAAa,GAAG,EAAE,YAAY,IAAI,CAAC,WAAW;AACxD,iBAAA;AAAA,YACL,GAAG;AAAA,YACH,cAAc,OAAO,eAAe;AAAA,YACpC,eAAe,OAAO,gBAAgB;AAAA,YACtC,OAAO,OAAO,QAAQ;AAAA,YACtB,QAAQ,OAAO,SAAS;AAAA,UAC1B;AAAA,QACD,CAAA;AAAA,MACH;AAAA,IACD,CAAA;AAAA,EACH;AACF;ACeO,MAAM,gBAAN,MAAM,sBAAqB,WAKhC;AAAA,EAmBA,YACkB,IAChB,UACQ,QACR;;AACA,UAAM,IAAI,QAAQ;AAJF,SAAA,KAAA;AAER,SAAA,SAAA;AAjBV,SAAQ,eAAuB;AAC/B,SAAQ,kBAA4B,SAAS;AAE7C,SAAQ,cAAsB;AAC9B,SAAQ,cAAuB;AAE/B,SAAiB,mBAAmB,sBAAuC;AAC3E,SAAiB,UAAU,sBAA2C;AACtE,SAAiB,UAAU,sBAAqC;AAChE,SAAiB,SAAS,sBAAmC;AAC7D,SAAiB,kBAAkB,sBAAsC;AACzE,SAAiB,cAAc,sBAAyC;AACxE,SAAiB,eAAe,sBAA+B;AAS7D,SAAK,WAAW,KAAK,SAAS,UAA0B,UAAU,EAAG,SAAS;AAE9E,SAAK,iBAAiB;AAAA,MACpB,WAAS,UAAK,WAAL,mBAAa,YAAW;AAAA,MACjC,aAAa,KAAK,SAAS,eAAe;AAAA,MAC1C,cAAY,UAAK,WAAL,mBAAa,eAAc;AAAA,IACzC;AAEA,SAAK,aACH,UAAK,WAAL,mBAAa,cAAa,eAAe,aACrC,IAAI,yBAAyB,KAAK,cAAc,IAChD,IAAI,uBAAuB,KAAK,cAAc;AAE/C,SAAA,eAAc,UAAK,WAAL,mBAAa;AAC3B,SAAA,eAAe,KAAK,UAAU,KAAK;AACnC,SAAA,kBAAkB,KAAK,UAAU,KAAK;AAEtC,SAAA,SAAS,iBAAiB,CAAC,aAAa;AAC3C,UAAI,KAAK,MAAM,gBAAgB,cAAc,CAAC,SAAS,mBAAmB;AAExE,aAAK,mBAAmB;AAAA,MAAA;AAAA,IAC1B,CACD;AAEI,SAAA,SAAS,iBAAiB,CAAC,OAAO,KAAK,cAAc,KAAK,eAAe,EAAE,CAAC,GAAG;AAAA,MAClF,MAAM;AAAA,MACN,MAAM;AAAA,IAAA,CACP;AACD,SAAK,UAAU,SAAS,cAAc,CAAC,SAAS,UAAU;AAClD,YAAA,aAAa,MAAM,KAAK,MAAM;AAC/B,WAAA,SAAS,iBAAiB,UAAU,CAAC;AAC1C,WAAK,YAAY,KAAK,EAAE,YAAY,KAAK,aAAa,YAAY;AAC7D,WAAA,WAAW,wBAAwB,MAAM,IAAI,GAAG,KAAK,SAAS,YAAY;AAAA,IAAA,CAChF;AACD,SAAK,UAAU;AAAA,MAAS;AAAA,MAAc,CAAC,SAAS,UAC9C,KAAK,WAAW,wBAAwB,MAAM,IAAI,GAAG,KAAK,SAAS,WAAY,CAAA;AAAA,IACjF;AACA,SAAK,UAAU;AAAA,MAAS;AAAA,MAAW,CAAC,SAAS,UAC3C,KAAK,WAAW,wBAAwB,MAAM,IAAI,GAAG,KAAK,SAAS,WAAY,CAAA;AAAA,IACjF;AAAA,EAAA;AAAA,EAGM,gBAAgB,YAAoB,WAA2B,UAAU;AAC/E,UAAM,kBAAmC;AAAA,MACvC,YAAY;AAAA,MACZ;AAAA,MACA,UAAU,KAAK;AAAA,MACf,WAAW,KAAK,IAAI;AAAA,IACtB;AAEK,SAAA,SAAS,mBAAmB,eAAe,CAAC;AAGjD,QAAI,aAAa,WAAW;AAE1B,WAAK,mBAAmB;AAAA,IAAA;AAAA,EAC1B;AAAA,EAGM,qBAAqB;AAC3B,QAAI,CAAC,KAAK,MAAM,gBAAgB,WAAY;AAE5C,UAAM,kBAAmC;AAAA,MACvC,YAAY;AAAA,MACZ,YAAY,KAAK,MAAM,gBAAgB;AAAA,MACvC,UAAU,KAAK,MAAM,gBAAgB;AAAA,MACrC,WAAW,KAAK,MAAM,gBAAgB;AAAA,IACxC;AAEK,SAAA,SAAS,mBAAmB,eAAe,CAAC;AAAA,EAAA;AAAA;AAAA;AAAA;AAAA,EAO3C,cAAc,OAAyC;AAC7D,UAAM,eAAe,KAAK,SAAS,mBAAmB,KAAK;AAC3D,UAAM,mBAAmB,KAAK,SAAS,oBAAoB,YAAY;AAChE,WAAA,EAAE,cAAc,iBAAiB;AAAA,EAAA;AAAA,EAGlC,eAAe,IAAqB,QAAuB,KAAK,MAAM,cAAc;AAC1F,WAAO,KAAK,SAAS,aAAa,IAAI,OAAO,KAAK,YAAY;AAAA,EAAA;AAAA;AAAA;AAAA;AAAA,EAOxD,OAAO,YAA2B,MAAc;AAEjD,SAAA,SAAS,kBAAkB,UAAU,CAAC;AAG3C,QAAI,6BAAM,OAAQ,MAAK,QAAQ,KAAK,KAAK,MAAM;AAC/C,QAAI,6BAAM,SAAS;AACZ,WAAA,QAAQ,KAAK,KAAK,OAAO;AAE9B,UAAI,KAAK,QAAQ,gBAAgB,KAAK,aAAa;AAC5C,aAAA,cAAc,KAAK,QAAQ;AAC3B,aAAA,YAAY,KAAK,EAAE,YAAY,KAAK,aAAa,YAAY,KAAK,MAAM,WAAA,CAAY;AAAA,MAAA;AAAA,IAC3F;AAIF,SAAK,gBAAgB,KAAK,KAAK,kBAAA,CAAmB;AAAA,EAAA;AAAA;AAAA,EAI5C,cAAc,SAAwB;AAC5C,SAAK,OAAO,SAAS,EAAE,QAAA,CAAS;AAAA,EAAA;AAAA;AAAA,EAI1B,WAAW,OAAyC,IAAqB;AACzE,UAAA,SAAS,KAAK,cAAc,KAAK;AACvC,UAAM,UAAU,KAAK,eAAe,IAAI,OAAO,YAAY;AAEtD,SAAA,OAAO,EAAE,GAAG,QAAQ,GAAG,WAAW,EAAE,QAAQ,SAAS;AAAA,EAAA;AAAA,EAGpD,2BAA0C;AACzC,WAAA,KAAK,MAAM,gBAAgB,CAAC;AAAA,EAAA;AAAA,EAG9B,eAAe,UAAyD;AACtE,WAAA,KAAK,gBAAgB,GAAG,QAAQ;AAAA,EAAA;AAAA,EAGlC,oBAAoC;AACnC,UAAA,QAAQ,KAAK,UAAU,KAAK;AAC3B,WAAA,kBAAkB,KAAK,OAAO,KAAK;AAAA,EAAA;AAAA,EAGpC,mBAAmB;AACzB,SAAK,gBAAgB,KAAK,KAAK,kBAAA,CAAmB;AAAA,EAAA;AAAA,EAG3C,eAAe,WAAwB,UAA6B;AAC3E,SAAK,iBAAiB;AAElB,QAAA,UAAU,oBAAoB,SAAS,iBAAiB;AACrD,WAAA,iBAAiB,KAAK,SAAS,eAAe;AAAA,IAAA;AAAA,EACrD;AAAA,EAGO,mBACP,WACA,UACM;AACN,QAAI,UAAU,KAAK,UAAU,SAAS,KAAK,OAAO;AAC3C,WAAA,eAAe,SAAS,KAAK;AAClC,WAAK,cAAc,KAAK,eAAe,KAAK,SAAS,WAAA,CAAY,CAAC;AAAA,IAAA;AAEpE,QAAI,UAAU,KAAK,aAAa,SAAS,KAAK,UAAU;AACjD,WAAA,kBAAkB,SAAS,KAAK;AAAA,IAAA;AAAA,EACvC;AAAA;AAAA;AAAA;AAAA;AAAA,EAOM,kBAAkB,aAA6B;AAGlD,QAAA,gBAAgB,eAAe,cAC9B,KAAK,oBAAoB,4BAC1B,gBAAgB,eAAe,YAAY,KAAK,oBAAoB,wBACrE;AACA;AAAA,IAAA;AAGF,SAAK,WACH,gBAAgB,eAAe,aAC3B,IAAI,yBAAyB,KAAK,cAAc,IAChD,IAAI,uBAAuB,KAAK,cAAc;AAG/C,SAAA;AAAA,MACH,kBAAkB;AAAA,QAChB,UAAU;AAAA,MACX,CAAA;AAAA,IACH;AAGA,UAAM,QAAQ,wBAAwB,KAAK,UAAU,IAAI;AACzD,SAAK,WAAW,OAAO,KAAK,SAAS,YAAY;AAAA,EAAA;AAAA,EAG5C,iBAAiB;AACtB,QAAI,KAAK,YAAa;AAEtB,SAAK,cAAc;AACd,SAAA,aAAa,KAAK,IAAI;AAE3B,QAAI,KAAK,aAAa;AACpB,WAAK,aAAa,EAAE,YAAY,KAAK,aAAa,UAAU,WAAW;AAAA,IAAA;AAAA,EACzE;AAAA,EAGQ,kBAAoC;AACrC,WAAA;AAAA,MACL,eAAe,KAAK,OAAO;AAAA,MAC3B,gBAAgB,KAAK,QAAQ;AAAA,MAC7B,UAAU,KAAK,QAAQ;AAAA,MACvB,cAAc,KAAK,YAAY;AAAA,MAC/B,eAAe,KAAK,aAAa;AAAA,MACjC,mBAAmB,KAAK,iBAAiB;AAAA,MACzC,gBAAgB,MAAM,KAAK;AAAA,MAC3B,eAAe,MAAM,KAAK,MAAM;AAAA,MAChC,oBAAoB,MAAM,KAAK,MAAM;AAAA,MACrC,cAAc,KAAK,aAAa,KAAK,IAAI;AAAA,MACzC,kBAAkB,KAAK,iBAAiB,KAAK,IAAI;AAAA,MACjD,sBAAsB,KAAK,qBAAqB,KAAK,IAAI;AAAA,MACzD,YAAY,KAAK,WAAW,KAAK,IAAI;AAAA,MACrC,WAAW,KAAK,UAAU,KAAK,IAAI;AAAA,MACnC,wBAAwB,KAAK,uBAAuB,KAAK,IAAI;AAAA,MAC7D,YAAY,MAAM,KAAK,MAAM;AAAA,MAC7B,mBAAmB,CAAC,aAA6B,KAAK,kBAAkB,QAAQ;AAAA,IAClF;AAAA,EAAA;AAAA,EAGM,aAAa,SAA8B;AACjD,UAAM,EAAE,YAAY,WAAW,UAAU,iBAAiB,SAAS,UAAU;AACxE,SAAA,gBAAgB,YAAY,QAAQ;AACnC,UAAA,eAAe,KAAK,yBAAyB;AAC7C,UAAA,WAAW,KAAK,SAAS;AAAA,MAC7B;AAAA,MACA;AAAA,MACA,KAAK;AAAA,MACL,KAAK;AAAA,MACL;AAAA,IACF;AACA,QAAI,UAAU;AACZ,WAAK,SAAS,SAAS,EAAE,GAAG,UAAU,UAAU,QAAQ;AAAA,IAAA,OACnD;AAEL,WAAK,mBAAmB;AAAA,IAAA;AAAA,EAC1B;AAAA,EAGM,iBAAiB,WAA2B,UAAU;AACtD,UAAA,eAAe,KAAK,yBAAyB;AACnD,UAAM,mBAAmB,aAAa;AAAA,MAAU,CAAC,SAC/C,KAAK,YAAY,SAAS,KAAK,WAAW;AAAA,IAC5C;AACA,QAAI,oBAAoB,KAAK,mBAAmB,aAAa,SAAS,GAAG;AACjE,YAAA,WAAW,aAAa,mBAAmB,CAAC;AAC5C,YAAA,aAAa,SAAS,YAAY,CAAC;AACpC,WAAA,gBAAgB,YAAY,QAAQ;AAEnC,YAAA,WAAW,KAAK,SAAS;AAAA,QAC7B,SAAS,YAAY,CAAC;AAAA,QACtB;AAAA,QACA,KAAK;AAAA,QACL,KAAK;AAAA,MACP;AACA,UAAI,UAAU;AACZ,aAAK,SAAS,SAAS,EAAE,GAAG,UAAU,UAAU;AAAA,MAAA,OAC3C;AAEL,aAAK,mBAAmB;AAAA,MAAA;AAAA,IAC1B;AAAA,EACF;AAAA,EAGM,qBAAqB,WAA2B,UAAU;AAC1D,UAAA,eAAe,KAAK,yBAAyB;AACnD,UAAM,mBAAmB,aAAa;AAAA,MAAU,CAAC,SAC/C,KAAK,YAAY,SAAS,KAAK,WAAW;AAAA,IAC5C;AACA,QAAI,mBAAmB,GAAG;AAClB,YAAA,WAAW,aAAa,mBAAmB,CAAC;AAC5C,YAAA,aAAa,SAAS,YAAY,CAAC;AACpC,WAAA,gBAAgB,YAAY,QAAQ;AAEnC,YAAA,WAAW,KAAK,SAAS;AAAA,QAC7B,SAAS,YAAY,CAAC;AAAA,QACtB;AAAA,QACA,KAAK;AAAA,QACL,KAAK;AAAA,MACP;AACA,UAAI,UAAU;AACZ,aAAK,SAAS,SAAS,EAAE,GAAG,UAAU,UAAU;AAAA,MAAA,OAC3C;AAEL,aAAK,mBAAmB;AAAA,MAAA;AAAA,IAC1B;AAAA,EACF;AAAA,EAGM,WAAW,UAA2C;AAC5D,UAAM,UAAU,YAAY,KAAK,SAAS,WAAW;AAC/C,UAAA,eAAe,KAAK,yBAAyB;AACnD,WAAO,KAAK,SAAS,aAAa,SAAS,cAAc,KAAK,YAAY;AAAA,EAAA;AAAA,EAGpE,YAAiC;AAChC,WAAA;AAAA,MACL,cAAc,KAAK,MAAM;AAAA,MACzB,kBAAkB,KAAK,MAAM;AAAA,IAC/B;AAAA,EAAA;AAAA,EAGM,uBACN,WACA,MACA,OACA,UACa;AACb,WAAO,KAAK,SAAS;AAAA,MACnB,YAAY;AAAA,MACZ,KAAK,MAAM;AAAA,MACX,SAAS,KAAK;AAAA,MACd,YAAY,KAAK;AAAA,MACjB;AAAA,IACF;AAAA,EAAA;AAAA,EAGF,MAAM,aAA4B;AAAA,EAAA;AAAA,EAIlC,MAAM,UAAyB;AAC7B,SAAK,QAAQ,MAAM;AACnB,SAAK,QAAQ,MAAM;AACnB,SAAK,YAAY,MAAM;AACvB,SAAK,OAAO,MAAM;AAClB,SAAK,gBAAgB,MAAM;AAC3B,SAAK,aAAa,MAAM;AACxB,SAAK,iBAAiB,MAAM;AAC5B,UAAM,QAAQ;AAAA,EAAA;AAElB;AAxWE,cAAgB,KAAK;AANhB,IAAM,eAAN;ACrCA,MAAM,mBAAmB;AAEzB,MAAM,WAA+C;AAAA,EAC1D,IAAI;AAAA,EACJ,MAAM;AAAA,EACN,SAAS;AAAA,EACT,UAAU,CAAC,QAAQ;AAAA,EACnB,UAAU,CAAC,UAAU;AAAA,EACrB,UAAU,CAAC;AAAA,EACX,eAAe;AAAA,IACb,SAAS;AAAA,IACT,SAAS;AAAA,EAAA;AAEb;ACAO,MAAM,uBAAsC;AAAA,EACjD,aAAa;AAAA,EACb,cAAc,CAAC;AAAA,EACf,uBAAuB,CAAC;AAAA,EACxB,qBAAqB,CAAC;AAAA,EACtB,cAAc,EAAE,GAAG,GAAG,GAAG,EAAE;AAAA,EAC3B,cAAc;AAAA,EACd,YAAY;AACd;AAEO,MAAM,yBAA0C;AAAA,EACrD,YAAY;AAAA,EACZ,YAAY;AAAA,EACZ,UAAU;AAAA,EACV,WAAW;AACb;AAEa,MAAA,eAAkF,CAC7F,WACA,YACI;AAAA,EACJ,cAAc,CAAC;AAAA,EACf,YAAY,UAAU,MAAM;AAAA,EAC5B,kBAAkB,EAAE,OAAO,GAAG,QAAQ,EAAE;AAAA,EACxC,uBAAuB,EAAE,GAAG,GAAG,GAAG,EAAE;AAAA,EACpC,UAAU,OAAO,YAAY,eAAe;AAAA,EAC5C,SAAS,OAAO,WAAW;AAAA,EAC3B,OAAO,UAAU;AAAA,EACjB,iBAAiB;AAAA,EACjB,GAAG;AACL;AAEa,MAAA,gBAAqE,CAChF,OACA,WACG;AACH,UAAQ,OAAO,MAAM;AAAA,IACnB,KAAK;AACH,aAAO,EAAE,GAAG,OAAO,YAAY,OAAO,QAAQ;AAAA,IAChD,KAAK;AACH,aAAO,EAAE,GAAG,OAAO,OAAO,OAAO,QAAQ;AAAA,IAC3C,KAAK;AACH,aAAO,EAAE,GAAG,OAAO,GAAG,OAAO,QAAQ;AAAA,IACvC,KAAK;AACH,aAAO,EAAE,GAAG,OAAO,uBAAuB,OAAO,QAAQ;AAAA,IAC3D,KAAK;AACH,aAAO,EAAE,GAAG,OAAO,iBAAiB,OAAO,QAAQ;AAAA,IACrD;AACS,aAAA;AAAA,EAAA;AAEb;AC3DO,MAAM,sBAKT;AAAA,EACF;AAAA,EACA,QAAQ,CAAC,UAAU,WAAW,IAAI,aAAa,kBAAkB,UAAU,MAAM;AAAA,EACjF,SAAS;AAAA,EACT,cAAc,CAAC,WAAW,WAAW,aAAa,WAAW,MAAM;AACrE;"}
|
package/dist/lib/actions.d.ts
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import { Action } from '@embedpdf/core';
|
|
2
|
-
import { ScrollState } from './types';
|
|
2
|
+
import { PageChangeState, ScrollState } from './types';
|
|
3
3
|
export declare const UPDATE_SCROLL_STATE = "UPDATE_SCROLL_STATE";
|
|
4
4
|
export declare const SET_DESIRED_SCROLL_POSITION = "SET_DESIRED_SCROLL_POSITION";
|
|
5
5
|
export declare const UPDATE_TOTAL_PAGES = "UPDATE_TOTAL_PAGES";
|
|
6
|
+
export declare const SET_PAGE_CHANGE_STATE = "SET_PAGE_CHANGE_STATE";
|
|
6
7
|
export interface UpdateScrollStateAction extends Action {
|
|
7
8
|
type: typeof UPDATE_SCROLL_STATE;
|
|
8
9
|
payload: Partial<ScrollState>;
|
|
@@ -18,10 +19,15 @@ export interface UpdateTotalPagesAction extends Action {
|
|
|
18
19
|
type: typeof UPDATE_TOTAL_PAGES;
|
|
19
20
|
payload: number;
|
|
20
21
|
}
|
|
21
|
-
export
|
|
22
|
+
export interface SetPageChangeStateAction extends Action {
|
|
23
|
+
type: typeof SET_PAGE_CHANGE_STATE;
|
|
24
|
+
payload: PageChangeState;
|
|
25
|
+
}
|
|
26
|
+
export type ScrollAction = UpdateScrollStateAction | SetDesiredScrollPositionAction | UpdateTotalPagesAction | SetPageChangeStateAction;
|
|
22
27
|
export declare function updateScrollState(payload: Partial<ScrollState>): UpdateScrollStateAction;
|
|
23
28
|
export declare function setDesiredScrollPosition(payload: {
|
|
24
29
|
x: number;
|
|
25
30
|
y: number;
|
|
26
31
|
}): SetDesiredScrollPositionAction;
|
|
27
32
|
export declare function updateTotalPages(payload: number): UpdateTotalPagesAction;
|
|
33
|
+
export declare function setPageChangeState(payload: PageChangeState): SetPageChangeStateAction;
|
package/dist/lib/reducer.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { Reducer, CoreState, SetScaleAction } from '@embedpdf/core';
|
|
2
|
-
import { ScrollState, ScrollPluginConfig, ScrollMetrics } from './types';
|
|
2
|
+
import { ScrollState, ScrollPluginConfig, ScrollMetrics, PageChangeState } from './types';
|
|
3
3
|
import { ScrollAction } from './actions';
|
|
4
4
|
export declare const defaultScrollMetrics: ScrollMetrics;
|
|
5
|
+
export declare const defaultPageChangeState: PageChangeState;
|
|
5
6
|
export declare const initialState: (coreState: CoreState, config: ScrollPluginConfig) => ScrollState;
|
|
6
7
|
export declare const scrollReducer: Reducer<ScrollState, ScrollAction | SetScaleAction>;
|
|
@@ -13,6 +13,7 @@ export declare class ScrollPlugin extends BasePlugin<ScrollPluginConfig, ScrollC
|
|
|
13
13
|
private initialPage?;
|
|
14
14
|
private currentPage;
|
|
15
15
|
private layoutReady;
|
|
16
|
+
private readonly pageChangeState$;
|
|
16
17
|
private readonly layout$;
|
|
17
18
|
private readonly scroll$;
|
|
18
19
|
private readonly state$;
|
|
@@ -20,6 +21,8 @@ export declare class ScrollPlugin extends BasePlugin<ScrollPluginConfig, ScrollC
|
|
|
20
21
|
private readonly pageChange$;
|
|
21
22
|
private readonly layoutReady$;
|
|
22
23
|
constructor(id: string, registry: PluginRegistry, config?: ScrollPluginConfig | undefined);
|
|
24
|
+
private startPageChange;
|
|
25
|
+
private completePageChange;
|
|
23
26
|
private computeLayout;
|
|
24
27
|
private computeMetrics;
|
|
25
28
|
private commit;
|
|
@@ -29,7 +32,7 @@ export declare class ScrollPlugin extends BasePlugin<ScrollPluginConfig, ScrollC
|
|
|
29
32
|
onScrollerData(callback: (layout: ScrollerLayout) => void): Unsubscribe;
|
|
30
33
|
getScrollerLayout(): ScrollerLayout;
|
|
31
34
|
private pushScrollLayout;
|
|
32
|
-
onStoreUpdated(
|
|
35
|
+
onStoreUpdated(prevState: ScrollState, newState: ScrollState): void;
|
|
33
36
|
onCoreStoreUpdated(prevState: StoreState<CoreState>, newState: StoreState<CoreState>): void;
|
|
34
37
|
/**
|
|
35
38
|
* Change the scroll strategy at runtime (e.g., vertical <-> horizontal)
|
package/dist/lib/types.d.ts
CHANGED
|
@@ -3,6 +3,12 @@ import { PdfPageObject, Rect, Rotation } from '@embedpdf/models';
|
|
|
3
3
|
import { ViewportMetrics } from '@embedpdf/plugin-viewport';
|
|
4
4
|
import { VirtualItem } from './types/virtual-item';
|
|
5
5
|
export type ScrollBehavior = 'instant' | 'smooth' | 'auto';
|
|
6
|
+
export interface PageChangeState {
|
|
7
|
+
isChanging: boolean;
|
|
8
|
+
targetPage: number;
|
|
9
|
+
fromPage: number;
|
|
10
|
+
startTime: number;
|
|
11
|
+
}
|
|
6
12
|
export interface ScrollState extends ScrollMetrics {
|
|
7
13
|
virtualItems: VirtualItem[];
|
|
8
14
|
totalPages: number;
|
|
@@ -17,6 +23,7 @@ export interface ScrollState extends ScrollMetrics {
|
|
|
17
23
|
strategy: ScrollStrategy;
|
|
18
24
|
pageGap: number;
|
|
19
25
|
scale: number;
|
|
26
|
+
pageChangeState: PageChangeState;
|
|
20
27
|
}
|
|
21
28
|
export interface ScrollerLayout {
|
|
22
29
|
startSpacing: number;
|
|
@@ -97,8 +104,10 @@ export interface ScrollCapability {
|
|
|
97
104
|
onScroll: EventHook<ScrollMetrics>;
|
|
98
105
|
getCurrentPage(): number;
|
|
99
106
|
getTotalPages(): number;
|
|
107
|
+
getPageChangeState(): PageChangeState;
|
|
100
108
|
onPageChange: EventHook<PageChangePayload>;
|
|
101
109
|
onLayoutChange: EventHook<LayoutChangePayload>;
|
|
110
|
+
onPageChangeState: EventHook<PageChangeState>;
|
|
102
111
|
onLayoutReady: EventHook<boolean>;
|
|
103
112
|
scrollToPage(options: ScrollToPageOptions): void;
|
|
104
113
|
scrollToNextPage(behavior?: ScrollBehavior): void;
|
|
@@ -108,4 +117,5 @@ export interface ScrollCapability {
|
|
|
108
117
|
getRectPositionForPage(page: number, rect: Rect, scale?: number, rotation?: Rotation): Rect | null;
|
|
109
118
|
setScrollStrategy(strategy: ScrollStrategy): void;
|
|
110
119
|
getPageGap(): number;
|
|
120
|
+
getPageChangeState: () => PageChangeState;
|
|
111
121
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@embedpdf/plugin-scroll",
|
|
3
|
-
"version": "1.3.
|
|
3
|
+
"version": "1.3.6",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"main": "./dist/index.cjs",
|
|
@@ -29,22 +29,22 @@
|
|
|
29
29
|
}
|
|
30
30
|
},
|
|
31
31
|
"dependencies": {
|
|
32
|
-
"@embedpdf/models": "1.3.
|
|
32
|
+
"@embedpdf/models": "1.3.6"
|
|
33
33
|
},
|
|
34
34
|
"devDependencies": {
|
|
35
35
|
"@types/react": "^18.2.0",
|
|
36
36
|
"typescript": "^5.0.0",
|
|
37
37
|
"@embedpdf/build": "1.0.1",
|
|
38
|
-
"@embedpdf/
|
|
39
|
-
"@embedpdf/
|
|
38
|
+
"@embedpdf/core": "1.3.6",
|
|
39
|
+
"@embedpdf/plugin-viewport": "1.3.6"
|
|
40
40
|
},
|
|
41
41
|
"peerDependencies": {
|
|
42
42
|
"preact": "^10.26.4",
|
|
43
43
|
"react": ">=16.8.0",
|
|
44
44
|
"react-dom": ">=16.8.0",
|
|
45
45
|
"vue": ">=3.2.0",
|
|
46
|
-
"@embedpdf/core": "1.3.
|
|
47
|
-
"@embedpdf/plugin-viewport": "1.3.
|
|
46
|
+
"@embedpdf/core": "1.3.6",
|
|
47
|
+
"@embedpdf/plugin-viewport": "1.3.6"
|
|
48
48
|
},
|
|
49
49
|
"files": [
|
|
50
50
|
"dist",
|