@embedpdf/plugin-zoom 2.0.0-next.0 → 2.0.0-next.2

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 CHANGED
@@ -1,2 +1,2 @@
1
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("@embedpdf/core"),t=require("@embedpdf/models");var o=(e=>(e.Automatic="automatic",e.FitPage="fit-page",e.FitWidth="fit-width",e))(o||{}),i=(e=>(e[e.Center=0]="Center",e[e.Top=1]="Top",e))(i||{});const n="zoom",a={id:n,name:"Zoom Plugin",version:"1.0.0",provides:["zoom"],requires:["viewport","scroll"],optional:["interaction-manager","spread"],defaultConfig:{enabled:!0,defaultZoomLevel:o.Automatic,minZoom:.2,maxZoom:60,zoomStep:.1,zoomRanges:[{min:.2,max:.5,step:.05},{min:.5,max:1,step:.1},{min:1,max:2,step:.2},{min:2,max:4,step:.4},{min:4,max:10,step:.8},{min:10,max:20,step:1.6},{min:20,max:40,step:3.2},{min:40,max:60,step:6.4}],presets:[{name:"Fit Page",value:o.FitPage},{name:"Fit Width",value:o.FitWidth},{name:"Automatic",value:o.Automatic},{name:"25%",value:.25},{name:"50%",value:.5},{name:"100%",value:1},{name:"125%",value:1.25},{name:"150%",value:1.5},{name:"200%",value:2},{name:"400%",value:4},{name:"800%",value:8},{name:"1600%",value:16}]}},r="ZOOM/INIT_STATE",s="ZOOM/CLEANUP_STATE",m="ZOOM/SET_ZOOM_LEVEL",c="ZOOM/SET_MARQUEE_ZOOM_ACTIVE";const l={zoomLevel:o.Automatic,currentZoomLevel:1,isMarqueeZoomActive:!1},u={documents:{},activeDocumentId:null};const d=class extends e.BasePlugin{constructor(t,o,n){var a,r,s;super(t,o),this.zoom$=e.createEmitter(),this.state$=e.createBehaviorEmitter(),this.viewportPlugin=o.getPlugin("viewport"),this.viewport=this.viewportPlugin.provides(),this.scroll=o.getPlugin("scroll").provides();const m=o.getPlugin("interaction-manager");this.interactionManager=(null==m?void 0:m.provides())??null;const l=o.getPlugin("spread");this.spread=(null==l?void 0:l.provides())??null,this.minZoom=n.minZoom??.25,this.maxZoom=n.maxZoom??10,this.zoomStep=n.zoomStep??.1,this.defaultZoomLevel=n.defaultZoomLevel,this.presets=n.presets??[],this.zoomRanges=this.normalizeRanges(n.zoomRanges??[]),this.viewport.onViewportResize(e=>this.recalcAuto(e.documentId,i.Top),{mode:"debounce",wait:150,keyExtractor:e=>e.documentId}),null==(a=this.spread)||a.onSpreadChange(e=>{this.recalcAuto(e.documentId,i.Top)}),null==(r=this.interactionManager)||r.registerMode({id:"marqueeZoom",scope:"page",exclusive:!0,cursor:"zoom-in"}),null==(s=this.interactionManager)||s.onModeChange(e=>{const t="marqueeZoom"===e.activeMode,o=this.getDocumentState(e.documentId);var i;o&&o.isMarqueeZoomActive!==t&&this.dispatch((i=e.documentId,{type:c,payload:{documentId:i,isActive:t}}))})}onDocumentLoadingStarted(e){this.viewport.gate("zoom",e);const t={...l,zoomLevel:this.defaultZoomLevel};this.dispatch(function(e,t){return{type:r,payload:{documentId:e,state:t}}}(e,t)),this.logger.debug("ZoomPlugin","DocumentOpened",`Initialized zoom state for document: ${e}`)}onDocumentLoaded(e){this.recalcAuto(e,i.Top)}onDocumentClosed(e){this.dispatch(function(e){return{type:s,payload:e}}(e)),this.logger.debug("ZoomPlugin","DocumentClosed",`Cleaned up zoom state for document: ${e}`)}onRotationChanged(e){this.recalcAuto(e,i.Top)}buildCapability(){return{requestZoom:(e,t)=>this.requestZoom(e,t),requestZoomBy:(e,t)=>this.requestZoomBy(e,t),zoomIn:()=>this.zoomIn(),zoomOut:()=>this.zoomOut(),zoomToArea:(e,t)=>this.zoomToArea(e,t),enableMarqueeZoom:()=>this.enableMarqueeZoom(),disableMarqueeZoom:()=>this.disableMarqueeZoom(),toggleMarqueeZoom:()=>this.toggleMarqueeZoom(),isMarqueeZoomActive:()=>this.isMarqueeZoomActive(),getState:()=>this.getDocumentStateOrThrow(),forDocument:e=>this.createZoomScope(e),registerMarqueeOnPage:e=>this.registerMarqueeOnPage(e),getPresets:()=>this.presets,onZoomChange:this.zoom$.on,onStateChange:this.state$.on}}createZoomScope(e){return{requestZoom:(t,o)=>this.requestZoom(t,o,e),requestZoomBy:(t,o)=>this.requestZoomBy(t,o,e),zoomIn:()=>this.zoomIn(e),zoomOut:()=>this.zoomOut(e),zoomToArea:(t,o)=>this.zoomToArea(t,o,e),enableMarqueeZoom:()=>this.enableMarqueeZoom(e),disableMarqueeZoom:()=>this.disableMarqueeZoom(e),toggleMarqueeZoom:()=>this.toggleMarqueeZoom(e),isMarqueeZoomActive:()=>this.isMarqueeZoomActive(e),getState:()=>this.getDocumentStateOrThrow(e),onZoomChange:t=>this.zoom$.on(o=>{o.documentId===e&&t(o)}),onStateChange:t=>this.state$.on(o=>{o.documentId===e&&t(o.state)})}}getDocumentState(e){const t=e??this.getActiveDocumentId();return this.state.documents[t]??null}getDocumentStateOrThrow(e){const t=this.getDocumentState(e);if(!t)throw new Error(`Zoom state not found for document: ${e??"active"}`);return t}requestZoom(e,t,o){this.handleRequest({level:e,center:t},o)}requestZoomBy(e,t,o){const i=o??this.getActiveDocumentId(),n=this.getDocumentStateOrThrow(i).currentZoomLevel,a=this.toZoom(n+e);this.handleRequest({level:a,center:t},i)}zoomIn(e){const t=e??this.getActiveDocumentId(),o=this.getDocumentStateOrThrow(t).currentZoomLevel;this.handleRequest({level:o,delta:this.stepFor(o)},t)}zoomOut(e){const t=e??this.getActiveDocumentId(),o=this.getDocumentStateOrThrow(t).currentZoomLevel;this.handleRequest({level:o,delta:-this.stepFor(o)},t)}zoomToArea(e,t,o){const i=o??this.getActiveDocumentId();this.handleZoomToArea(i,e,t)}enableMarqueeZoom(e){var t;const o=e??this.getActiveDocumentId();null==(t=this.interactionManager)||t.forDocument(o).activate("marqueeZoom")}disableMarqueeZoom(e){var t;const o=e??this.getActiveDocumentId();null==(t=this.interactionManager)||t.forDocument(o).activateDefaultMode()}toggleMarqueeZoom(e){var t;const o=e??this.getActiveDocumentId(),i=null==(t=this.interactionManager)?void 0:t.forDocument(o);"marqueeZoom"===(null==i?void 0:i.getActiveMode())?i.activateDefaultMode():null==i||i.activate("marqueeZoom")}isMarqueeZoomActive(e){var t;const o=e??this.getActiveDocumentId();return"marqueeZoom"===(null==(t=this.interactionManager)?void 0:t.forDocument(o).getActiveMode())}handleRequest({level:t,delta:o=0,center:n,focus:a=i.Center,align:r="keep"},s){const c=s??this.getActiveDocumentId(),l=this.getDocumentStateOrThrow(c);if(!this.coreState.core.documents[c])return;const u=this.viewport.forDocument(c),d=u.getMetrics(),h=l.currentZoomLevel;if(0===d.clientWidth||0===d.clientHeight)return;const g="number"==typeof t?t:this.computeZoomForMode(c,t,d);if(!1===g)return;const p=e.clamp(g+o,this.minZoom,this.maxZoom),v=Math.floor(1e3*p)/1e3,Z=n??{vx:d.clientWidth/2,vy:a===i.Top?0:d.clientHeight/2},{desiredScrollLeft:M,desiredScrollTop:z}=this.computeScrollForZoomChange(c,d,h,v,Z,r);isNaN(M)||isNaN(z)||this.viewportPlugin.setViewportScrollMetrics(c,{scrollLeft:M,scrollTop:z}),this.dispatch(function(e,t,o){return{type:m,payload:{documentId:e,zoomLevel:t,currentZoomLevel:o}}}(c,"number"==typeof t?v:t,v)),this.dispatchCoreAction(e.setScale(v,c)),this.viewport.isGated(c)&&this.viewport.releaseGate("zoom",c),u.scrollTo({x:M,y:z,behavior:"instant"});const f={documentId:c,oldZoom:h,newZoom:v,level:t,center:Z,desiredScrollLeft:M,desiredScrollTop:z,viewport:d};this.zoom$.emit(f)}computeZoomForMode(e,t,i){if(!this.coreState.core.documents[e])return!1;const n=this.scroll.forDocument(e),a=n?this.scroll.getPageGap():0,r=this.viewport.getViewportGap(),s=n.getSpreadPagesWithRotatedSize();if(!s.length)return!1;if(0===i.clientWidth||0===i.clientHeight)return!1;const m=i.clientWidth-2*r,c=i.clientHeight-2*r;if(m<=0||c<=0)return!1;let l=0,u=0;switch(s.forEach(e=>{const t=e.reduce((e,t,o)=>e+t.rotatedSize.width+(o?a:0),0),o=Math.max(...e.map(e=>e.rotatedSize.height));l=Math.max(l,t),u=Math.max(u,o)}),t){case o.FitWidth:return m/l;case o.FitPage:return Math.min(m/l,c/u);case o.Automatic:return Math.min(m/l,1);default:return 1}}computeScrollForZoomChange(e,t,o,i,n,a="keep"){const r=this.scroll.forDocument(e).getLayout(),s=this.viewport.getViewportGap(),m=r.totalContentSize.width,c=r.totalContentSize.height,l=t.clientWidth-2*s,u=t.clientHeight-2*s,d=(e,t,o)=>t*o<e?(e-t*o)/2:0,h=d(l,m,o),g=d(u,c,o),p=d(l,m,i),v=d(u,c,i),Z=(t.scrollLeft+n.vx-s-h)/o*i+s+p,M=(t.scrollTop+n.vy-s-g)/o*i+s+v,z="center"===a?Z-t.clientWidth/2:Z-n.vx,f="center"===a?M-t.clientHeight/2:M-n.vy;return{desiredScrollLeft:Math.max(0,z),desiredScrollTop:Math.max(0,f)}}handleZoomToArea(e,o,i){const n=this.coreState.core.documents[e];if(!n)return;const a=n.rotation,r=this.viewport.forDocument(e).getMetrics(),s=this.viewport.getViewportGap(),m=this.getDocumentStateOrThrow(e).currentZoomLevel,c=r.clientWidth-2*s,l=r.clientHeight-2*s,u=this.scroll.forDocument(e).getLayout(),d=u.virtualItems.find(e=>e.pageLayouts.some(e=>e.pageIndex===o));if(!d)return;const h=d.pageLayouts.find(e=>e.pageIndex===o),g=t.rotateRect({width:h.width,height:h.height},i,a),p=this.toZoom(Math.min(c/g.size.width,l/g.size.height)),v=d.x+h.x,Z=d.y+h.y,M=v+g.origin.x+g.size.width/2,z=Z+g.origin.y+g.size.height/2,f=(e,t,o)=>t*o<e?(e-t*o)/2:0,S=f(c,u.totalContentSize.width,m),I=f(l,u.totalContentSize.height,m),D=s+S+M*m-r.scrollLeft,q=s+I+z*m-r.scrollTop;this.handleRequest({level:p,center:{vx:D,vy:q},align:"center"},e)}recalcAuto(e,t){const i=this.getDocumentState(e);i&&(i.zoomLevel!==o.Automatic&&i.zoomLevel!==o.FitPage&&i.zoomLevel!==o.FitWidth||this.handleRequest({level:i.zoomLevel,focus:t},e))}normalizeRanges(e){return[...e].filter(e=>e.step>0&&e.max>e.min).sort((e,t)=>e.min-t.min)}stepFor(e){const t=this.zoomRanges.find(t=>e>=t.min&&e<t.max);return t?t.step:this.zoomStep}toZoom(t){return parseFloat(e.clamp(t,this.minZoom,this.maxZoom).toFixed(2))}registerMarqueeOnPage(t){if(!this.interactionManager)return this.logger.warn("ZoomPlugin","MissingDependency","Interaction manager plugin not loaded, marquee zoom disabled"),()=>{};const o=this.coreState.core.documents[t.documentId];if(!o||!o.document)return this.logger.warn("ZoomPlugin","DocumentNotFound","Document not found"),()=>{};const i=o.document.pages[t.pageIndex];if(!i)return this.logger.warn("ZoomPlugin","PageNotFound",`Page ${t.pageIndex} not found`),()=>{};const n=function(t){const{pageSize:o,scale:i,minDragPx:n=5,onPreview:a,onCommit:r,onSmallDrag:s}=t;let m=null,c=null;return{onPointerDown:(e,t)=>{var o;m=e,c={origin:{x:e.x,y:e.y},size:{width:0,height:0}},null==a||a(c),null==(o=t.setPointerCapture)||o.call(t)},onPointerMove:t=>{if(!m)return;const i=e.clamp(t.x,0,o.width),n=e.clamp(t.y,0,o.height);c={origin:{x:Math.min(m.x,i),y:Math.min(m.y,n)},size:{width:Math.abs(i-m.x),height:Math.abs(n-m.y)}},null==a||a(c)},onPointerUp:(e,t)=>{var o;c&&(Math.max(c.size.width,c.size.height)*i>n?null==r||r(c):null==s||s()),m=null,c=null,null==a||a(null),null==(o=t.releasePointerCapture)||o.call(t)},onPointerCancel:(e,t)=>{var o;m=null,c=null,null==a||a(null),null==(o=t.releasePointerCapture)||o.call(t)}}}({pageSize:i.size,scale:t.scale,onPreview:t.callback.onPreview,onCommit:e=>{var o,i;this.zoomToArea(t.pageIndex,e,t.documentId),null==(i=(o=t.callback).onCommit)||i.call(o,e)},onSmallDrag:()=>{var e,o;this.zoomIn(t.documentId),null==(o=(e=t.callback).onSmallDrag)||o.call(e)}});return this.interactionManager.registerHandlers({documentId:t.documentId,modeId:"marqueeZoom",handlers:n,pageIndex:t.pageIndex})}onStoreUpdated(e,t){for(const o in t.documents){const i=e.documents[o],n=t.documents[o];i&&n&&(i.currentZoomLevel!==n.currentZoomLevel||i.zoomLevel!==n.zoomLevel||i.isMarqueeZoomActive!==n.isMarqueeZoomActive)&&this.state$.emit({documentId:o,state:n})}}async initialize(){this.logger.info("ZoomPlugin","Initialize","Zoom plugin initialized")}async destroy(){this.zoom$.clear(),this.state$.clear(),super.destroy()}};d.id="zoom";let h=d;const g={manifest:a,create:(e,t)=>new h(n,e,t),reducer:(e=u,t)=>{switch(t.type){case r:{const{documentId:o,state:i}=t.payload;return{...e,documents:{...e.documents,[o]:i},activeDocumentId:e.activeDocumentId??o}}case s:{const o=t.payload,{[o]:i,...n}=e.documents;return{...e,documents:n,activeDocumentId:e.activeDocumentId===o?null:e.activeDocumentId}}case"ZOOM/SET_ACTIVE_DOCUMENT":return{...e,activeDocumentId:t.payload};case m:{const{documentId:o,zoomLevel:i,currentZoomLevel:n}=t.payload,a=e.documents[o];return a?{...e,documents:{...e.documents,[o]:{...a,zoomLevel:i,currentZoomLevel:n}}}:e}case c:{const{documentId:o,isActive:i}=t.payload,n=e.documents[o];return n?{...e,documents:{...e.documents,[o]:{...n,isMarqueeZoomActive:i}}}:e}default:return e}},initialState:u};exports.VerticalZoomFocus=i,exports.ZOOM_PLUGIN_ID=n,exports.ZoomMode=o,exports.ZoomPlugin=h,exports.ZoomPluginPackage=g,exports.initialDocumentState=l,exports.initialState=u,exports.manifest=a;
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("@embedpdf/core"),t=require("@embedpdf/models");var o=(e=>(e.Automatic="automatic",e.FitPage="fit-page",e.FitWidth="fit-width",e))(o||{}),i=(e=>(e[e.Center=0]="Center",e[e.Top=1]="Top",e))(i||{});const n="zoom",a={id:n,name:"Zoom Plugin",version:"1.0.0",provides:["zoom"],requires:["viewport","scroll"],optional:["interaction-manager","spread"],defaultConfig:{defaultZoomLevel:o.Automatic,minZoom:.2,maxZoom:60,zoomStep:.1,zoomRanges:[{min:.2,max:.5,step:.05},{min:.5,max:1,step:.1},{min:1,max:2,step:.2},{min:2,max:4,step:.4},{min:4,max:10,step:.8},{min:10,max:20,step:1.6},{min:20,max:40,step:3.2},{min:40,max:60,step:6.4}],presets:[{name:"Fit Page",value:o.FitPage},{name:"Fit Width",value:o.FitWidth},{name:"Automatic",value:o.Automatic},{name:"25%",value:.25},{name:"50%",value:.5},{name:"100%",value:1},{name:"125%",value:1.25},{name:"150%",value:1.5},{name:"200%",value:2},{name:"400%",value:4},{name:"800%",value:8},{name:"1600%",value:16}]}},r="ZOOM/INIT_STATE",s="ZOOM/CLEANUP_STATE",m="ZOOM/SET_ZOOM_LEVEL",c="ZOOM/SET_MARQUEE_ZOOM_ACTIVE";const l={zoomLevel:o.Automatic,currentZoomLevel:1,isMarqueeZoomActive:!1},u={documents:{},activeDocumentId:null};const d=class extends e.BasePlugin{constructor(t,o,n){var a,r,s;super(t,o),this.zoom$=e.createEmitter(),this.state$=e.createBehaviorEmitter(),this.viewportPlugin=o.getPlugin("viewport"),this.viewport=this.viewportPlugin.provides(),this.scroll=o.getPlugin("scroll").provides();const m=o.getPlugin("interaction-manager");this.interactionManager=(null==m?void 0:m.provides())??null;const l=o.getPlugin("spread");this.spread=(null==l?void 0:l.provides())??null,this.minZoom=n.minZoom??.25,this.maxZoom=n.maxZoom??10,this.zoomStep=n.zoomStep??.1,this.defaultZoomLevel=n.defaultZoomLevel,this.presets=n.presets??[],this.zoomRanges=this.normalizeRanges(n.zoomRanges??[]),this.viewport.onViewportResize(e=>this.recalcAuto(e.documentId,i.Top),{mode:"debounce",wait:150,keyExtractor:e=>e.documentId}),null==(a=this.spread)||a.onSpreadChange(e=>{this.recalcAuto(e.documentId,i.Top)}),null==(r=this.interactionManager)||r.registerMode({id:"marqueeZoom",scope:"page",exclusive:!0,cursor:"zoom-in"}),null==(s=this.interactionManager)||s.onModeChange(e=>{const t="marqueeZoom"===e.activeMode,o=this.getDocumentState(e.documentId);var i;o&&o.isMarqueeZoomActive!==t&&this.dispatch((i=e.documentId,{type:c,payload:{documentId:i,isActive:t}}))})}onDocumentLoadingStarted(e){this.viewport.gate("zoom",e);const t={...l,zoomLevel:this.defaultZoomLevel};this.dispatch(function(e,t){return{type:r,payload:{documentId:e,state:t}}}(e,t)),this.logger.debug("ZoomPlugin","DocumentOpened",`Initialized zoom state for document: ${e}`)}onDocumentLoaded(e){this.recalcAuto(e,i.Top)}onDocumentClosed(e){this.dispatch(function(e){return{type:s,payload:e}}(e)),this.logger.debug("ZoomPlugin","DocumentClosed",`Cleaned up zoom state for document: ${e}`)}onRotationChanged(e){this.recalcAuto(e,i.Top)}buildCapability(){return{requestZoom:(e,t)=>this.requestZoom(e,t),requestZoomBy:(e,t)=>this.requestZoomBy(e,t),zoomIn:()=>this.zoomIn(),zoomOut:()=>this.zoomOut(),zoomToArea:(e,t)=>this.zoomToArea(e,t),enableMarqueeZoom:()=>this.enableMarqueeZoom(),disableMarqueeZoom:()=>this.disableMarqueeZoom(),toggleMarqueeZoom:()=>this.toggleMarqueeZoom(),isMarqueeZoomActive:()=>this.isMarqueeZoomActive(),getState:()=>this.getDocumentStateOrThrow(),forDocument:e=>this.createZoomScope(e),registerMarqueeOnPage:e=>this.registerMarqueeOnPage(e),getPresets:()=>this.presets,onZoomChange:this.zoom$.on,onStateChange:this.state$.on}}createZoomScope(e){return{requestZoom:(t,o)=>this.requestZoom(t,o,e),requestZoomBy:(t,o)=>this.requestZoomBy(t,o,e),zoomIn:()=>this.zoomIn(e),zoomOut:()=>this.zoomOut(e),zoomToArea:(t,o)=>this.zoomToArea(t,o,e),enableMarqueeZoom:()=>this.enableMarqueeZoom(e),disableMarqueeZoom:()=>this.disableMarqueeZoom(e),toggleMarqueeZoom:()=>this.toggleMarqueeZoom(e),isMarqueeZoomActive:()=>this.isMarqueeZoomActive(e),getState:()=>this.getDocumentStateOrThrow(e),onZoomChange:t=>this.zoom$.on(o=>{o.documentId===e&&t(o)}),onStateChange:t=>this.state$.on(o=>{o.documentId===e&&t(o.state)})}}getDocumentState(e){const t=e??this.getActiveDocumentId();return this.state.documents[t]??null}getDocumentStateOrThrow(e){const t=this.getDocumentState(e);if(!t)throw new Error(`Zoom state not found for document: ${e??"active"}`);return t}requestZoom(e,t,o){this.handleRequest({level:e,center:t},o)}requestZoomBy(e,t,o){const i=o??this.getActiveDocumentId(),n=this.getDocumentStateOrThrow(i).currentZoomLevel,a=this.toZoom(n+e);this.handleRequest({level:a,center:t},i)}zoomIn(e){const t=e??this.getActiveDocumentId(),o=this.getDocumentStateOrThrow(t).currentZoomLevel;this.handleRequest({level:o,delta:this.stepFor(o)},t)}zoomOut(e){const t=e??this.getActiveDocumentId(),o=this.getDocumentStateOrThrow(t).currentZoomLevel;this.handleRequest({level:o,delta:-this.stepFor(o)},t)}zoomToArea(e,t,o){const i=o??this.getActiveDocumentId();this.handleZoomToArea(i,e,t)}enableMarqueeZoom(e){var t;const o=e??this.getActiveDocumentId();null==(t=this.interactionManager)||t.forDocument(o).activate("marqueeZoom")}disableMarqueeZoom(e){var t;const o=e??this.getActiveDocumentId();null==(t=this.interactionManager)||t.forDocument(o).activateDefaultMode()}toggleMarqueeZoom(e){var t;const o=e??this.getActiveDocumentId(),i=null==(t=this.interactionManager)?void 0:t.forDocument(o);"marqueeZoom"===(null==i?void 0:i.getActiveMode())?i.activateDefaultMode():null==i||i.activate("marqueeZoom")}isMarqueeZoomActive(e){var t;const o=e??this.getActiveDocumentId();return"marqueeZoom"===(null==(t=this.interactionManager)?void 0:t.forDocument(o).getActiveMode())}handleRequest({level:t,delta:o=0,center:n,focus:a=i.Center,align:r="keep"},s){const c=s??this.getActiveDocumentId(),l=this.getDocumentStateOrThrow(c);if(!this.coreState.core.documents[c])return;const u=this.viewport.forDocument(c),d=u.getMetrics(),h=l.currentZoomLevel;if(0===d.clientWidth||0===d.clientHeight)return;const g="number"==typeof t?t:this.computeZoomForMode(c,t,d);if(!1===g)return;const p=e.clamp(g+o,this.minZoom,this.maxZoom),v=Math.floor(1e3*p)/1e3,Z=n??{vx:d.clientWidth/2,vy:a===i.Top?0:d.clientHeight/2},{desiredScrollLeft:M,desiredScrollTop:z}=this.computeScrollForZoomChange(c,d,h,v,Z,r);isNaN(M)||isNaN(z)||this.viewportPlugin.setViewportScrollMetrics(c,{scrollLeft:M,scrollTop:z}),this.dispatch(function(e,t,o){return{type:m,payload:{documentId:e,zoomLevel:t,currentZoomLevel:o}}}(c,"number"==typeof t?v:t,v)),this.dispatchCoreAction(e.setScale(v,c)),this.viewport.isGated(c)&&this.viewport.releaseGate("zoom",c),u.scrollTo({x:M,y:z,behavior:"instant"});const f={documentId:c,oldZoom:h,newZoom:v,level:t,center:Z,desiredScrollLeft:M,desiredScrollTop:z,viewport:d};this.zoom$.emit(f)}computeZoomForMode(e,t,i){if(!this.coreState.core.documents[e])return!1;const n=this.scroll.forDocument(e),a=n?this.scroll.getPageGap():0,r=this.viewport.getViewportGap(),s=n.getSpreadPagesWithRotatedSize();if(!s.length)return!1;if(0===i.clientWidth||0===i.clientHeight)return!1;const m=i.clientWidth-2*r,c=i.clientHeight-2*r;if(m<=0||c<=0)return!1;let l=0,u=0;switch(s.forEach(e=>{const t=e.reduce((e,t,o)=>e+t.rotatedSize.width+(o?a:0),0),o=Math.max(...e.map(e=>e.rotatedSize.height));l=Math.max(l,t),u=Math.max(u,o)}),t){case o.FitWidth:return m/l;case o.FitPage:return Math.min(m/l,c/u);case o.Automatic:return Math.min(m/l,1);default:return 1}}computeScrollForZoomChange(e,t,o,i,n,a="keep"){const r=this.scroll.forDocument(e).getLayout(),s=this.viewport.getViewportGap(),m=r.totalContentSize.width,c=r.totalContentSize.height,l=t.clientWidth-2*s,u=t.clientHeight-2*s,d=(e,t,o)=>t*o<e?(e-t*o)/2:0,h=d(l,m,o),g=d(u,c,o),p=d(l,m,i),v=d(u,c,i),Z=(t.scrollLeft+n.vx-s-h)/o*i+s+p,M=(t.scrollTop+n.vy-s-g)/o*i+s+v,z="center"===a?Z-t.clientWidth/2:Z-n.vx,f="center"===a?M-t.clientHeight/2:M-n.vy;return{desiredScrollLeft:Math.max(0,z),desiredScrollTop:Math.max(0,f)}}handleZoomToArea(e,o,i){const n=this.coreState.core.documents[e];if(!n)return;const a=n.rotation,r=this.viewport.forDocument(e).getMetrics(),s=this.viewport.getViewportGap(),m=this.getDocumentStateOrThrow(e).currentZoomLevel,c=r.clientWidth-2*s,l=r.clientHeight-2*s,u=this.scroll.forDocument(e).getLayout(),d=u.virtualItems.find(e=>e.pageLayouts.some(e=>e.pageIndex===o));if(!d)return;const h=d.pageLayouts.find(e=>e.pageIndex===o),g=t.rotateRect({width:h.width,height:h.height},i,a),p=this.toZoom(Math.min(c/g.size.width,l/g.size.height)),v=d.x+h.x,Z=d.y+h.y,M=v+g.origin.x+g.size.width/2,z=Z+g.origin.y+g.size.height/2,f=(e,t,o)=>t*o<e?(e-t*o)/2:0,S=f(c,u.totalContentSize.width,m),I=f(l,u.totalContentSize.height,m),D=s+S+M*m-r.scrollLeft,q=s+I+z*m-r.scrollTop;this.handleRequest({level:p,center:{vx:D,vy:q},align:"center"},e)}recalcAuto(e,t){const i=this.getDocumentState(e);i&&(i.zoomLevel!==o.Automatic&&i.zoomLevel!==o.FitPage&&i.zoomLevel!==o.FitWidth||this.handleRequest({level:i.zoomLevel,focus:t},e))}normalizeRanges(e){return[...e].filter(e=>e.step>0&&e.max>e.min).sort((e,t)=>e.min-t.min)}stepFor(e){const t=this.zoomRanges.find(t=>e>=t.min&&e<t.max);return t?t.step:this.zoomStep}toZoom(t){return parseFloat(e.clamp(t,this.minZoom,this.maxZoom).toFixed(2))}registerMarqueeOnPage(t){if(!this.interactionManager)return this.logger.warn("ZoomPlugin","MissingDependency","Interaction manager plugin not loaded, marquee zoom disabled"),()=>{};const o=this.coreState.core.documents[t.documentId];if(!o||!o.document)return this.logger.warn("ZoomPlugin","DocumentNotFound","Document not found"),()=>{};const i=o.document.pages[t.pageIndex];if(!i)return this.logger.warn("ZoomPlugin","PageNotFound",`Page ${t.pageIndex} not found`),()=>{};const n=function(t){const{pageSize:o,scale:i,minDragPx:n=5,onPreview:a,onCommit:r,onSmallDrag:s}=t;let m=null,c=null;return{onPointerDown:(e,t)=>{var o;m=e,c={origin:{x:e.x,y:e.y},size:{width:0,height:0}},null==a||a(c),null==(o=t.setPointerCapture)||o.call(t)},onPointerMove:t=>{if(!m)return;const i=e.clamp(t.x,0,o.width),n=e.clamp(t.y,0,o.height);c={origin:{x:Math.min(m.x,i),y:Math.min(m.y,n)},size:{width:Math.abs(i-m.x),height:Math.abs(n-m.y)}},null==a||a(c)},onPointerUp:(e,t)=>{var o;c&&(Math.max(c.size.width,c.size.height)*i>n?null==r||r(c):null==s||s()),m=null,c=null,null==a||a(null),null==(o=t.releasePointerCapture)||o.call(t)},onPointerCancel:(e,t)=>{var o;m=null,c=null,null==a||a(null),null==(o=t.releasePointerCapture)||o.call(t)}}}({pageSize:i.size,scale:t.scale,onPreview:t.callback.onPreview,onCommit:e=>{var o,i;this.zoomToArea(t.pageIndex,e,t.documentId),null==(i=(o=t.callback).onCommit)||i.call(o,e)},onSmallDrag:()=>{var e,o;this.zoomIn(t.documentId),null==(o=(e=t.callback).onSmallDrag)||o.call(e)}});return this.interactionManager.registerHandlers({documentId:t.documentId,modeId:"marqueeZoom",handlers:n,pageIndex:t.pageIndex})}onStoreUpdated(e,t){for(const o in t.documents){const i=e.documents[o],n=t.documents[o];i&&n&&(i.currentZoomLevel!==n.currentZoomLevel||i.zoomLevel!==n.zoomLevel||i.isMarqueeZoomActive!==n.isMarqueeZoomActive)&&this.state$.emit({documentId:o,state:n})}}async initialize(){this.logger.info("ZoomPlugin","Initialize","Zoom plugin initialized")}async destroy(){this.zoom$.clear(),this.state$.clear(),super.destroy()}};d.id="zoom";let h=d;const g={manifest:a,create:(e,t)=>new h(n,e,t),reducer:(e=u,t)=>{switch(t.type){case r:{const{documentId:o,state:i}=t.payload;return{...e,documents:{...e.documents,[o]:i},activeDocumentId:e.activeDocumentId??o}}case s:{const o=t.payload,{[o]:i,...n}=e.documents;return{...e,documents:n,activeDocumentId:e.activeDocumentId===o?null:e.activeDocumentId}}case"ZOOM/SET_ACTIVE_DOCUMENT":return{...e,activeDocumentId:t.payload};case m:{const{documentId:o,zoomLevel:i,currentZoomLevel:n}=t.payload,a=e.documents[o];return a?{...e,documents:{...e.documents,[o]:{...a,zoomLevel:i,currentZoomLevel:n}}}:e}case c:{const{documentId:o,isActive:i}=t.payload,n=e.documents[o];return n?{...e,documents:{...e.documents,[o]:{...n,isMarqueeZoomActive:i}}}:e}default:return e}},initialState:u};exports.VerticalZoomFocus=i,exports.ZOOM_PLUGIN_ID=n,exports.ZoomMode=o,exports.ZoomPlugin=h,exports.ZoomPluginPackage=g,exports.initialDocumentState=l,exports.initialState=u,exports.manifest=a;
2
2
  //# sourceMappingURL=index.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.cjs","sources":["../src/lib/types.ts","../src/lib/manifest.ts","../src/lib/actions.ts","../src/lib/reducer.ts","../src/lib/zoom-plugin.ts","../src/lib/handlers/marquee-zoom.handler.ts","../src/lib/index.ts"],"sourcesContent":["import { BasePluginConfig, EventHook } from '@embedpdf/core';\nimport { Rect } from '@embedpdf/models';\nimport { ViewportMetrics } from '@embedpdf/plugin-viewport';\n\n/* ------------------------------------------------------------------ */\n/* public */\n/* ------------------------------------------------------------------ */\n\nexport enum ZoomMode {\n Automatic = 'automatic',\n FitPage = 'fit-page',\n FitWidth = 'fit-width',\n}\n\nexport type ZoomLevel = ZoomMode | number;\n\nexport interface Point {\n vx: number;\n vy: number;\n}\n\nexport interface ZoomChangeEvent {\n documentId: string;\n /** old and new *actual* scale factors */\n oldZoom: number;\n newZoom: number;\n /** level used to obtain the newZoom (number | mode) */\n level: ZoomLevel;\n /** viewport point kept under the finger / mouse‑wheel focus */\n center: Point;\n /** where the viewport should scroll to after the scale change */\n desiredScrollLeft: number;\n desiredScrollTop: number;\n /** metrics at the moment the zoom was requested */\n viewport: ViewportMetrics;\n}\n\nexport interface StateChangeEvent {\n documentId: string;\n state: ZoomDocumentState;\n}\n\nexport interface MarqueeZoomCallback {\n onPreview?: (rect: Rect | null) => void;\n onCommit?: (rect: Rect) => void;\n onSmallDrag?: () => void;\n}\n\nexport interface RegisterMarqueeOnPageOptions {\n documentId: string;\n pageIndex: number;\n scale: number;\n callback: MarqueeZoomCallback;\n}\n\n// Per-document zoom state\nexport interface ZoomDocumentState {\n zoomLevel: ZoomLevel; // last **requested** level\n currentZoomLevel: number; // actual numeric factor\n isMarqueeZoomActive: boolean; // whether marquee zoom mode is active\n}\n\n// Scoped zoom capability\nexport interface ZoomScope {\n requestZoom(level: ZoomLevel, center?: Point): void;\n requestZoomBy(delta: number, center?: Point): void;\n zoomIn(): void;\n zoomOut(): void;\n zoomToArea(pageIndex: number, rect: Rect): void;\n enableMarqueeZoom(): void;\n disableMarqueeZoom(): void;\n toggleMarqueeZoom(): void;\n isMarqueeZoomActive(): boolean;\n getState(): ZoomDocumentState;\n onZoomChange: EventHook<ZoomChangeEvent>;\n onStateChange: EventHook<ZoomDocumentState>;\n}\n\nexport interface ZoomCapability {\n // Active document operations\n requestZoom(level: ZoomLevel, center?: Point): void;\n requestZoomBy(delta: number, center?: Point): void;\n zoomIn(): void;\n zoomOut(): void;\n zoomToArea(pageIndex: number, rect: Rect): void;\n enableMarqueeZoom(): void;\n disableMarqueeZoom(): void;\n toggleMarqueeZoom(): void;\n isMarqueeZoomActive(): boolean;\n getState(): ZoomDocumentState;\n\n // Document-scoped operations\n forDocument(documentId: string): ZoomScope;\n\n // Global\n registerMarqueeOnPage: (opts: RegisterMarqueeOnPageOptions) => () => void;\n getPresets(): ZoomPreset[];\n\n // Events (include documentId)\n onZoomChange: EventHook<ZoomChangeEvent>;\n onStateChange: EventHook<StateChangeEvent>;\n}\n\n/* ------------------------------------------------------------------ */\n/* config / store */\n/* ------------------------------------------------------------------ */\n\nexport interface ZoomRangeStep {\n min: number;\n max: number;\n step: number;\n}\n\nexport interface ZoomPreset {\n name: string;\n value: ZoomLevel;\n icon?: string;\n}\n\nexport interface ZoomPluginConfig extends BasePluginConfig {\n defaultZoomLevel: ZoomLevel;\n minZoom?: number;\n maxZoom?: number;\n zoomStep?: number;\n zoomRanges?: ZoomRangeStep[];\n presets?: ZoomPreset[];\n}\n\nexport interface ZoomState {\n // Per-document zoom state\n documents: Record<string, ZoomDocumentState>;\n activeDocumentId: string | null;\n}\n\nexport enum VerticalZoomFocus {\n Center,\n Top,\n}\n\nexport interface ZoomRequest {\n level: ZoomLevel;\n delta?: number;\n center?: Point;\n focus?: VerticalZoomFocus;\n align?: 'keep' | 'center';\n}\n","import { PluginManifest } from '@embedpdf/core';\n\nimport { ZoomMode, ZoomPluginConfig } from './types';\n\nexport const ZOOM_PLUGIN_ID = 'zoom';\n\nexport const manifest: PluginManifest<ZoomPluginConfig> = {\n id: ZOOM_PLUGIN_ID,\n name: 'Zoom Plugin',\n version: '1.0.0',\n provides: ['zoom'],\n requires: ['viewport', 'scroll'],\n optional: ['interaction-manager', 'spread'],\n defaultConfig: {\n enabled: true,\n defaultZoomLevel: ZoomMode.Automatic,\n minZoom: 0.2,\n maxZoom: 60,\n zoomStep: 0.1,\n zoomRanges: [\n {\n min: 0.2,\n max: 0.5,\n step: 0.05,\n },\n {\n min: 0.5,\n max: 1.0,\n step: 0.1,\n },\n {\n min: 1.0,\n max: 2.0,\n step: 0.2,\n },\n {\n min: 2.0,\n max: 4.0,\n step: 0.4,\n },\n {\n min: 4.0,\n max: 10.0,\n step: 0.8,\n },\n {\n min: 10.0,\n max: 20.0,\n step: 1.6,\n },\n {\n min: 20.0,\n max: 40.0,\n step: 3.2,\n },\n {\n min: 40.0,\n max: 60.0,\n step: 6.4,\n },\n ],\n presets: [\n {\n name: 'Fit Page',\n value: ZoomMode.FitPage,\n },\n {\n name: 'Fit Width',\n value: ZoomMode.FitWidth,\n },\n {\n name: 'Automatic',\n value: ZoomMode.Automatic,\n },\n {\n name: '25%',\n value: 0.25,\n },\n {\n name: '50%',\n value: 0.5,\n },\n {\n name: '100%',\n value: 1,\n },\n {\n name: '125%',\n value: 1.25,\n },\n {\n name: '150%',\n value: 1.5,\n },\n {\n name: '200%',\n value: 2,\n },\n {\n name: '400%',\n value: 4,\n },\n {\n name: '800%',\n value: 8,\n },\n {\n name: '1600%',\n value: 16,\n },\n ],\n },\n};\n","import { Action } from '@embedpdf/core';\nimport { ZoomLevel, ZoomDocumentState } from './types';\n\n// Document lifecycle\nexport const INIT_ZOOM_STATE = 'ZOOM/INIT_STATE';\nexport const CLEANUP_ZOOM_STATE = 'ZOOM/CLEANUP_STATE';\nexport const SET_ACTIVE_DOCUMENT = 'ZOOM/SET_ACTIVE_DOCUMENT';\n\n// Per-document actions\nexport const SET_ZOOM_LEVEL = 'ZOOM/SET_ZOOM_LEVEL';\nexport const SET_MARQUEE_ZOOM_ACTIVE = 'ZOOM/SET_MARQUEE_ZOOM_ACTIVE';\n\n// Document lifecycle actions\nexport interface InitZoomStateAction extends Action {\n type: typeof INIT_ZOOM_STATE;\n payload: {\n documentId: string;\n state: ZoomDocumentState;\n };\n}\n\nexport interface CleanupZoomStateAction extends Action {\n type: typeof CLEANUP_ZOOM_STATE;\n payload: string; // documentId\n}\n\nexport interface SetActiveDocumentAction extends Action {\n type: typeof SET_ACTIVE_DOCUMENT;\n payload: string | null; // documentId\n}\n\nexport interface SetZoomLevelAction extends Action {\n type: typeof SET_ZOOM_LEVEL;\n payload: {\n documentId: string;\n zoomLevel: ZoomLevel;\n currentZoomLevel: number;\n };\n}\n\nexport interface SetMarqueeZoomActiveAction extends Action {\n type: typeof SET_MARQUEE_ZOOM_ACTIVE;\n payload: {\n documentId: string;\n isActive: boolean;\n };\n}\n\nexport type ZoomAction =\n | InitZoomStateAction\n | CleanupZoomStateAction\n | SetActiveDocumentAction\n | SetZoomLevelAction\n | SetMarqueeZoomActiveAction;\n\n// Action Creators\nexport function initZoomState(documentId: string, state: ZoomDocumentState): InitZoomStateAction {\n return { type: INIT_ZOOM_STATE, payload: { documentId, state } };\n}\n\nexport function cleanupZoomState(documentId: string): CleanupZoomStateAction {\n return { type: CLEANUP_ZOOM_STATE, payload: documentId };\n}\n\nexport function setActiveDocument(documentId: string | null): SetActiveDocumentAction {\n return { type: SET_ACTIVE_DOCUMENT, payload: documentId };\n}\n\nexport function setZoomLevel(\n documentId: string,\n zoomLevel: ZoomLevel,\n currentZoomLevel: number,\n): SetZoomLevelAction {\n return { type: SET_ZOOM_LEVEL, payload: { documentId, zoomLevel, currentZoomLevel } };\n}\n\nexport function setMarqueeZoomActive(\n documentId: string,\n isActive: boolean,\n): SetMarqueeZoomActiveAction {\n return { type: SET_MARQUEE_ZOOM_ACTIVE, payload: { documentId, isActive } };\n}\n","import { Reducer } from '@embedpdf/core';\nimport {\n ZoomAction,\n INIT_ZOOM_STATE,\n CLEANUP_ZOOM_STATE,\n SET_ACTIVE_DOCUMENT,\n SET_ZOOM_LEVEL,\n SET_MARQUEE_ZOOM_ACTIVE,\n} from './actions';\nimport { ZoomState, ZoomDocumentState, ZoomMode } from './types';\n\nexport const initialDocumentState: ZoomDocumentState = {\n zoomLevel: ZoomMode.Automatic,\n currentZoomLevel: 1,\n isMarqueeZoomActive: false,\n};\n\nexport const initialState: ZoomState = {\n documents: {},\n activeDocumentId: null,\n};\n\nexport const zoomReducer: Reducer<ZoomState, ZoomAction> = (state = initialState, action) => {\n switch (action.type) {\n case INIT_ZOOM_STATE: {\n const { documentId, state: docState } = action.payload;\n return {\n ...state,\n documents: {\n ...state.documents,\n [documentId]: docState,\n },\n // Set as active if no active document\n activeDocumentId: state.activeDocumentId ?? documentId,\n };\n }\n\n case CLEANUP_ZOOM_STATE: {\n const documentId = action.payload;\n const { [documentId]: removed, ...remainingDocs } = state.documents;\n return {\n ...state,\n documents: remainingDocs,\n activeDocumentId: state.activeDocumentId === documentId ? null : state.activeDocumentId,\n };\n }\n\n case SET_ACTIVE_DOCUMENT: {\n return {\n ...state,\n activeDocumentId: action.payload,\n };\n }\n\n case SET_ZOOM_LEVEL: {\n const { documentId, zoomLevel, currentZoomLevel } = action.payload;\n const docState = state.documents[documentId];\n if (!docState) return state;\n\n return {\n ...state,\n documents: {\n ...state.documents,\n [documentId]: {\n ...docState,\n zoomLevel,\n currentZoomLevel,\n },\n },\n };\n }\n\n case SET_MARQUEE_ZOOM_ACTIVE: {\n const { documentId, isActive } = action.payload;\n const docState = state.documents[documentId];\n if (!docState) return state;\n\n return {\n ...state,\n documents: {\n ...state.documents,\n [documentId]: {\n ...docState,\n isMarqueeZoomActive: isActive,\n },\n },\n };\n }\n\n default:\n return state;\n }\n};\n","import {\n BasePlugin,\n PluginRegistry,\n createEmitter,\n clamp,\n setScale,\n createBehaviorEmitter,\n Listener,\n} from '@embedpdf/core';\nimport { ScrollPlugin, ScrollCapability } from '@embedpdf/plugin-scroll';\nimport { ViewportPlugin, ViewportCapability, ViewportMetrics } from '@embedpdf/plugin-viewport';\n\nimport {\n initZoomState,\n cleanupZoomState,\n setZoomLevel,\n ZoomAction,\n setMarqueeZoomActive,\n} from './actions';\nimport {\n ZoomPluginConfig,\n ZoomState,\n ZoomMode,\n Point,\n ZoomChangeEvent,\n ZoomCapability,\n ZoomPreset,\n ZoomRangeStep,\n VerticalZoomFocus,\n ZoomRequest,\n RegisterMarqueeOnPageOptions,\n ZoomScope,\n StateChangeEvent,\n ZoomDocumentState,\n} from './types';\nimport {\n InteractionManagerCapability,\n InteractionManagerPlugin,\n} from '@embedpdf/plugin-interaction-manager';\nimport { SpreadCapability, SpreadPlugin } from '@embedpdf/plugin-spread';\nimport { Rect, rotateRect } from '@embedpdf/models';\nimport { createMarqueeHandler } from './handlers';\nimport { initialDocumentState } from './reducer';\n\nexport class ZoomPlugin extends BasePlugin<\n ZoomPluginConfig,\n ZoomCapability,\n ZoomState,\n ZoomAction\n> {\n static readonly id = 'zoom' as const;\n\n private readonly zoom$ = createEmitter<ZoomChangeEvent>();\n private readonly state$ = createBehaviorEmitter<StateChangeEvent>();\n private readonly viewport: ViewportCapability;\n private readonly viewportPlugin: ViewportPlugin;\n private readonly scroll: ScrollCapability;\n private readonly interactionManager: InteractionManagerCapability | null;\n private readonly spread: SpreadCapability | null;\n private readonly presets: ZoomPreset[];\n private readonly zoomRanges: ZoomRangeStep[];\n private readonly defaultZoomLevel: ZoomMode | number;\n\n private readonly minZoom: number;\n private readonly maxZoom: number;\n private readonly zoomStep: number;\n\n constructor(id: string, registry: PluginRegistry, cfg: ZoomPluginConfig) {\n super(id, registry);\n\n this.viewportPlugin = registry.getPlugin<ViewportPlugin>('viewport')!;\n this.viewport = this.viewportPlugin.provides();\n this.scroll = registry.getPlugin<ScrollPlugin>('scroll')!.provides();\n const interactionManager = registry.getPlugin<InteractionManagerPlugin>('interaction-manager');\n this.interactionManager = interactionManager?.provides() ?? null;\n const spread = registry.getPlugin<SpreadPlugin>('spread');\n this.spread = spread?.provides() ?? null;\n\n this.minZoom = cfg.minZoom ?? 0.25;\n this.maxZoom = cfg.maxZoom ?? 10;\n this.zoomStep = cfg.zoomStep ?? 0.1;\n this.defaultZoomLevel = cfg.defaultZoomLevel;\n this.presets = cfg.presets ?? [];\n this.zoomRanges = this.normalizeRanges(cfg.zoomRanges ?? []);\n\n // Keep automatic modes up to date per document\n this.viewport.onViewportResize(\n (event) => this.recalcAuto(event.documentId, VerticalZoomFocus.Top),\n {\n mode: 'debounce',\n wait: 150,\n keyExtractor: (event) => event.documentId,\n },\n );\n\n // Subscribe to spread changes\n this.spread?.onSpreadChange((event) => {\n this.recalcAuto(event.documentId, VerticalZoomFocus.Top);\n });\n\n // Register marquee zoom mode\n this.interactionManager?.registerMode({\n id: 'marqueeZoom',\n scope: 'page',\n exclusive: true,\n cursor: 'zoom-in',\n });\n\n this.interactionManager?.onModeChange((state) => {\n // Track marquee zoom state changes for this document\n const isMarqueeActive = state.activeMode === 'marqueeZoom';\n const docState = this.getDocumentState(state.documentId);\n\n // Only dispatch if state actually changed\n if (docState && docState.isMarqueeZoomActive !== isMarqueeActive) {\n this.dispatch(setMarqueeZoomActive(state.documentId, isMarqueeActive));\n }\n });\n }\n\n // ─────────────────────────────────────────────────────────\n // Document Lifecycle Hooks (from BasePlugin)\n // ─────────────────────────────────────────────────────────\n\n protected override onDocumentLoadingStarted(documentId: string): void {\n this.viewport.gate('zoom', documentId);\n // Initialize zoom state for this document\n const docState: ZoomDocumentState = {\n ...initialDocumentState,\n zoomLevel: this.defaultZoomLevel,\n };\n\n this.dispatch(initZoomState(documentId, docState));\n\n this.logger.debug(\n 'ZoomPlugin',\n 'DocumentOpened',\n `Initialized zoom state for document: ${documentId}`,\n );\n }\n\n protected override onDocumentLoaded(documentId: string): void {\n // Apply initial zoom after document is fully loaded\n this.recalcAuto(documentId, VerticalZoomFocus.Top);\n }\n\n protected override onDocumentClosed(documentId: string): void {\n this.dispatch(cleanupZoomState(documentId));\n\n this.logger.debug(\n 'ZoomPlugin',\n 'DocumentClosed',\n `Cleaned up zoom state for document: ${documentId}`,\n );\n }\n\n protected override onRotationChanged(documentId: string): void {\n // Recalculate auto modes when rotation changes\n this.recalcAuto(documentId, VerticalZoomFocus.Top);\n }\n\n /*\n protected override onPagesChanged(documentId: string): void {\n // Recalculate auto modes when pages change\n this.recalcAuto(documentId, VerticalZoomFocus.Top);\n }*/\n\n // ─────────────────────────────────────────────────────────\n // Capability\n // ─────────────────────────────────────────────────────────\n\n protected buildCapability(): ZoomCapability {\n return {\n // Active document operations\n requestZoom: (level, c) => this.requestZoom(level, c),\n requestZoomBy: (d, c) => this.requestZoomBy(d, c),\n zoomIn: () => this.zoomIn(),\n zoomOut: () => this.zoomOut(),\n zoomToArea: (pageIndex, rect) => this.zoomToArea(pageIndex, rect),\n enableMarqueeZoom: () => this.enableMarqueeZoom(),\n disableMarqueeZoom: () => this.disableMarqueeZoom(),\n toggleMarqueeZoom: () => this.toggleMarqueeZoom(),\n isMarqueeZoomActive: () => this.isMarqueeZoomActive(),\n getState: () => this.getDocumentStateOrThrow(),\n\n // Document-scoped operations\n forDocument: (documentId: string) => this.createZoomScope(documentId),\n\n // Global\n registerMarqueeOnPage: (opts) => this.registerMarqueeOnPage(opts),\n getPresets: () => this.presets,\n\n // Events\n onZoomChange: this.zoom$.on,\n onStateChange: this.state$.on,\n };\n }\n\n // ─────────────────────────────────────────────────────────\n // Document Scoping\n // ─────────────────────────────────────────────────────────\n\n private createZoomScope(documentId: string): ZoomScope {\n return {\n requestZoom: (level, c) => this.requestZoom(level, c, documentId),\n requestZoomBy: (d, c) => this.requestZoomBy(d, c, documentId),\n zoomIn: () => this.zoomIn(documentId),\n zoomOut: () => this.zoomOut(documentId),\n zoomToArea: (pageIndex, rect) => this.zoomToArea(pageIndex, rect, documentId),\n enableMarqueeZoom: () => this.enableMarqueeZoom(documentId),\n disableMarqueeZoom: () => this.disableMarqueeZoom(documentId),\n toggleMarqueeZoom: () => this.toggleMarqueeZoom(documentId),\n isMarqueeZoomActive: () => this.isMarqueeZoomActive(documentId),\n getState: () => this.getDocumentStateOrThrow(documentId),\n onZoomChange: (listener: Listener<ZoomChangeEvent>) =>\n this.zoom$.on((event) => {\n if (event.documentId === documentId) listener(event);\n }),\n onStateChange: (listener: Listener<ZoomDocumentState>) =>\n this.state$.on((event) => {\n if (event.documentId === documentId) listener(event.state);\n }),\n };\n }\n\n // ─────────────────────────────────────────────────────────\n // State Helpers\n // ─────────────────────────────────────────────────────────\n\n private getDocumentState(documentId?: string): ZoomDocumentState | null {\n const id = documentId ?? this.getActiveDocumentId();\n return this.state.documents[id] ?? null;\n }\n\n private getDocumentStateOrThrow(documentId?: string): ZoomDocumentState {\n const state = this.getDocumentState(documentId);\n if (!state) {\n throw new Error(`Zoom state not found for document: ${documentId ?? 'active'}`);\n }\n return state;\n }\n\n // ─────────────────────────────────────────────────────────\n // Core Operations\n // ─────────────────────────────────────────────────────────\n\n private requestZoom(level: ZoomMode | number, center?: Point, documentId?: string): void {\n this.handleRequest({ level, center }, documentId);\n }\n\n private requestZoomBy(delta: number, center?: Point, documentId?: string): void {\n const id = documentId ?? this.getActiveDocumentId();\n const docState = this.getDocumentStateOrThrow(id);\n const cur = docState.currentZoomLevel;\n const target = this.toZoom(cur + delta);\n this.handleRequest({ level: target, center }, id);\n }\n\n private zoomIn(documentId?: string): void {\n const id = documentId ?? this.getActiveDocumentId();\n const docState = this.getDocumentStateOrThrow(id);\n const cur = docState.currentZoomLevel;\n this.handleRequest({ level: cur, delta: this.stepFor(cur) }, id);\n }\n\n private zoomOut(documentId?: string): void {\n const id = documentId ?? this.getActiveDocumentId();\n const docState = this.getDocumentStateOrThrow(id);\n const cur = docState.currentZoomLevel;\n this.handleRequest({ level: cur, delta: -this.stepFor(cur) }, id);\n }\n\n private zoomToArea(pageIndex: number, rect: Rect, documentId?: string): void {\n const id = documentId ?? this.getActiveDocumentId();\n this.handleZoomToArea(id, pageIndex, rect);\n }\n\n private enableMarqueeZoom(documentId?: string): void {\n const id = documentId ?? this.getActiveDocumentId();\n this.interactionManager?.forDocument(id).activate('marqueeZoom');\n }\n\n private disableMarqueeZoom(documentId?: string): void {\n const id = documentId ?? this.getActiveDocumentId();\n this.interactionManager?.forDocument(id).activateDefaultMode();\n }\n\n private toggleMarqueeZoom(documentId?: string): void {\n const id = documentId ?? this.getActiveDocumentId();\n const scope = this.interactionManager?.forDocument(id);\n if (scope?.getActiveMode() === 'marqueeZoom') {\n scope.activateDefaultMode();\n } else {\n scope?.activate('marqueeZoom');\n }\n }\n\n private isMarqueeZoomActive(documentId?: string): boolean {\n const id = documentId ?? this.getActiveDocumentId();\n return this.interactionManager?.forDocument(id).getActiveMode() === 'marqueeZoom';\n }\n\n // ─────────────────────────────────────────────────────────\n // Main Zoom Logic\n // ─────────────────────────────────────────────────────────\n\n private handleRequest(\n { level, delta = 0, center, focus = VerticalZoomFocus.Center, align = 'keep' }: ZoomRequest,\n documentId?: string,\n ) {\n const id = documentId ?? this.getActiveDocumentId();\n const docState = this.getDocumentStateOrThrow(id);\n const coreDoc = this.coreState.core.documents[id];\n if (!coreDoc) return;\n\n const viewport = this.viewport.forDocument(id);\n const metrics = viewport.getMetrics();\n const oldZoom = docState.currentZoomLevel;\n\n if (metrics.clientWidth === 0 || metrics.clientHeight === 0) {\n return;\n }\n\n // Step 1: Resolve target numeric zoom\n const base = typeof level === 'number' ? level : this.computeZoomForMode(id, level, metrics);\n\n if (base === false) return;\n\n const exactZoom = clamp(base + delta, this.minZoom, this.maxZoom);\n const newZoom = Math.floor(exactZoom * 1000) / 1000;\n\n // Step 2: Figure out viewport point to keep under focus\n const focusPoint: Point = center ?? {\n vx: metrics.clientWidth / 2,\n vy: focus === VerticalZoomFocus.Top ? 0 : metrics.clientHeight / 2,\n };\n\n // Step 3: Compute desired scroll offsets\n const { desiredScrollLeft, desiredScrollTop } = this.computeScrollForZoomChange(\n id,\n metrics,\n oldZoom,\n newZoom,\n focusPoint,\n align,\n );\n\n // Step 4: Dispatch and notify\n if (!isNaN(desiredScrollLeft) && !isNaN(desiredScrollTop)) {\n this.viewportPlugin.setViewportScrollMetrics(id, {\n scrollLeft: desiredScrollLeft,\n scrollTop: desiredScrollTop,\n });\n }\n\n this.dispatch(setZoomLevel(id, typeof level === 'number' ? newZoom : level, newZoom));\n this.dispatchCoreAction(setScale(newZoom, id));\n if (this.viewport.isGated(id)) {\n this.viewport.releaseGate('zoom', id);\n }\n\n viewport.scrollTo({\n x: desiredScrollLeft,\n y: desiredScrollTop,\n behavior: 'instant',\n });\n\n const evt: ZoomChangeEvent = {\n documentId: id,\n oldZoom,\n newZoom,\n level,\n center: focusPoint,\n desiredScrollLeft,\n desiredScrollTop,\n viewport: metrics,\n };\n\n this.zoom$.emit(evt);\n }\n\n private computeZoomForMode(\n documentId: string,\n mode: ZoomMode,\n vp: ViewportMetrics,\n ): number | false {\n const coreDoc = this.coreState.core.documents[documentId];\n if (!coreDoc) return false;\n\n const scrollScope = this.scroll.forDocument(documentId);\n const pgGap = scrollScope ? this.scroll.getPageGap() : 0;\n const vpGap = this.viewport.getViewportGap();\n\n const spreads = scrollScope.getSpreadPagesWithRotatedSize();\n if (!spreads.length) return false;\n\n if (vp.clientWidth === 0 || vp.clientHeight === 0) return false;\n\n const availableWidth = vp.clientWidth - 2 * vpGap;\n const availableHeight = vp.clientHeight - 2 * vpGap;\n\n if (availableWidth <= 0 || availableHeight <= 0) return false;\n\n let maxContentW = 0,\n maxContentH = 0;\n\n spreads.forEach((spread) => {\n const contentW = spread.reduce((s, p, i) => s + p.rotatedSize.width + (i ? pgGap : 0), 0);\n const contentH = Math.max(...spread.map((p) => p.rotatedSize.height));\n maxContentW = Math.max(maxContentW, contentW);\n maxContentH = Math.max(maxContentH, contentH);\n });\n\n switch (mode) {\n case ZoomMode.FitWidth:\n return availableWidth / maxContentW;\n case ZoomMode.FitPage:\n return Math.min(availableWidth / maxContentW, availableHeight / maxContentH);\n case ZoomMode.Automatic:\n return Math.min(availableWidth / maxContentW, 1);\n default:\n return 1;\n }\n }\n\n private computeScrollForZoomChange(\n documentId: string,\n vp: ViewportMetrics,\n oldZoom: number,\n newZoom: number,\n focus: Point,\n align: 'keep' | 'center' = 'keep',\n ) {\n const scrollScope = this.scroll.forDocument(documentId);\n const layout = scrollScope.getLayout();\n const vpGap = this.viewport.getViewportGap();\n\n const contentW = layout.totalContentSize.width;\n const contentH = layout.totalContentSize.height;\n\n const availableWidth = vp.clientWidth - 2 * vpGap;\n const availableHeight = vp.clientHeight - 2 * vpGap;\n\n const off = (availableSpace: number, cw: number, zoom: number) =>\n cw * zoom < availableSpace ? (availableSpace - cw * zoom) / 2 : 0;\n\n const offXold = off(availableWidth, contentW, oldZoom);\n const offYold = off(availableHeight, contentH, oldZoom);\n\n const offXnew = off(availableWidth, contentW, newZoom);\n const offYnew = off(availableHeight, contentH, newZoom);\n\n const cx = (vp.scrollLeft + focus.vx - vpGap - offXold) / oldZoom;\n const cy = (vp.scrollTop + focus.vy - vpGap - offYold) / oldZoom;\n\n const baseLeft = cx * newZoom + vpGap + offXnew;\n const baseTop = cy * newZoom + vpGap + offYnew;\n\n const desiredScrollLeft =\n align === 'center' ? baseLeft - vp.clientWidth / 2 : baseLeft - focus.vx;\n const desiredScrollTop =\n align === 'center' ? baseTop - vp.clientHeight / 2 : baseTop - focus.vy;\n\n return {\n desiredScrollLeft: Math.max(0, desiredScrollLeft),\n desiredScrollTop: Math.max(0, desiredScrollTop),\n };\n }\n\n private handleZoomToArea(documentId: string, pageIndex: number, rect: Rect) {\n const coreDoc = this.coreState.core.documents[documentId];\n if (!coreDoc) return;\n\n const rotation = coreDoc.rotation;\n const viewport = this.viewport.forDocument(documentId);\n const vp = viewport.getMetrics();\n const vpGap = this.viewport.getViewportGap();\n const docState = this.getDocumentStateOrThrow(documentId);\n const oldZ = docState.currentZoomLevel;\n\n const availableW = vp.clientWidth - 2 * vpGap;\n const availableH = vp.clientHeight - 2 * vpGap;\n\n const scrollScope = this.scroll.forDocument(documentId);\n const layout = scrollScope.getLayout();\n\n const vItem = layout.virtualItems.find((it) =>\n it.pageLayouts.some((p) => p.pageIndex === pageIndex),\n );\n if (!vItem) return;\n\n const pageRel = vItem.pageLayouts.find((p) => p.pageIndex === pageIndex)!;\n\n const rotatedRect = rotateRect(\n { width: pageRel.width, height: pageRel.height },\n rect,\n rotation,\n );\n\n const targetZoom = this.toZoom(\n Math.min(availableW / rotatedRect.size.width, availableH / rotatedRect.size.height),\n );\n\n const pageAbsX = vItem.x + pageRel.x;\n const pageAbsY = vItem.y + pageRel.y;\n\n const cxContent = pageAbsX + rotatedRect.origin.x + rotatedRect.size.width / 2;\n const cyContent = pageAbsY + rotatedRect.origin.y + rotatedRect.size.height / 2;\n\n const off = (avail: number, cw: number, z: number) =>\n cw * z < avail ? (avail - cw * z) / 2 : 0;\n\n const offXold = off(availableW, layout.totalContentSize.width, oldZ);\n const offYold = off(availableH, layout.totalContentSize.height, oldZ);\n\n const centerVX = vpGap + offXold + cxContent * oldZ - vp.scrollLeft;\n const centerVY = vpGap + offYold + cyContent * oldZ - vp.scrollTop;\n\n this.handleRequest(\n {\n level: targetZoom,\n center: { vx: centerVX, vy: centerVY },\n align: 'center',\n },\n documentId,\n );\n }\n\n private recalcAuto(documentId: string, focus?: VerticalZoomFocus) {\n const docState = this.getDocumentState(documentId);\n if (!docState) return;\n\n if (\n docState.zoomLevel === ZoomMode.Automatic ||\n docState.zoomLevel === ZoomMode.FitPage ||\n docState.zoomLevel === ZoomMode.FitWidth\n ) {\n this.handleRequest({ level: docState.zoomLevel, focus }, documentId);\n }\n }\n\n // ─────────────────────────────────────────────────────────\n // Helpers\n // ─────────────────────────────────────────────────────────\n\n private normalizeRanges(ranges: ZoomRangeStep[]): ZoomRangeStep[] {\n return [...ranges].filter((r) => r.step > 0 && r.max > r.min).sort((a, b) => a.min - b.min);\n }\n\n private stepFor(zoom: number): number {\n const r = this.zoomRanges.find((r) => zoom >= r.min && zoom < r.max);\n return r ? r.step : this.zoomStep;\n }\n\n private toZoom(v: number) {\n return parseFloat(clamp(v, this.minZoom, this.maxZoom).toFixed(2));\n }\n\n // ─────────────────────────────────────────────────────────\n // Marquee Zoom\n // ─────────────────────────────────────────────────────────\n\n public registerMarqueeOnPage(opts: RegisterMarqueeOnPageOptions) {\n if (!this.interactionManager) {\n this.logger.warn(\n 'ZoomPlugin',\n 'MissingDependency',\n 'Interaction manager plugin not loaded, marquee zoom disabled',\n );\n return () => {};\n }\n\n const coreDoc = this.coreState.core.documents[opts.documentId];\n if (!coreDoc || !coreDoc.document) {\n this.logger.warn('ZoomPlugin', 'DocumentNotFound', 'Document not found');\n return () => {};\n }\n\n const page = coreDoc.document.pages[opts.pageIndex];\n if (!page) {\n this.logger.warn('ZoomPlugin', 'PageNotFound', `Page ${opts.pageIndex} not found`);\n return () => {};\n }\n\n const handlers = createMarqueeHandler({\n pageSize: page.size,\n scale: opts.scale,\n onPreview: opts.callback.onPreview,\n onCommit: (rect) => {\n this.zoomToArea(opts.pageIndex, rect, opts.documentId);\n opts.callback.onCommit?.(rect);\n },\n onSmallDrag: () => {\n this.zoomIn(opts.documentId);\n opts.callback.onSmallDrag?.();\n },\n });\n\n const off = this.interactionManager.registerHandlers({\n documentId: opts.documentId,\n modeId: 'marqueeZoom',\n handlers,\n pageIndex: opts.pageIndex,\n });\n\n return off;\n }\n\n // ─────────────────────────────────────────────────────────\n // Store Update Handlers\n // ─────────────────────────────────────────────────────────\n\n override onStoreUpdated(prevState: ZoomState, newState: ZoomState): void {\n // Emit state changes for each changed document\n for (const documentId in newState.documents) {\n const prevDoc = prevState.documents[documentId];\n const newDoc = newState.documents[documentId];\n\n if (\n prevDoc &&\n newDoc &&\n (prevDoc.currentZoomLevel !== newDoc.currentZoomLevel ||\n prevDoc.zoomLevel !== newDoc.zoomLevel ||\n prevDoc.isMarqueeZoomActive !== newDoc.isMarqueeZoomActive)\n ) {\n this.state$.emit({\n documentId,\n state: newDoc,\n });\n }\n }\n }\n\n // ─────────────────────────────────────────────────────────\n // Lifecycle\n // ─────────────────────────────────────────────────────────\n\n async initialize(): Promise<void> {\n this.logger.info('ZoomPlugin', 'Initialize', 'Zoom plugin initialized');\n }\n\n async destroy() {\n this.zoom$.clear();\n this.state$.clear();\n super.destroy();\n }\n}\n","import { Position, Rect, Size } from '@embedpdf/models';\nimport { clamp } from '@embedpdf/core';\nimport {\n EmbedPdfPointerEvent,\n PointerEventHandlersWithLifecycle,\n} from '@embedpdf/plugin-interaction-manager';\n\nexport function createMarqueeHandler(opts: {\n pageSize: Size;\n scale: number;\n minDragPx?: number;\n onPreview?: (rect: Rect | null) => void;\n onCommit?: (rect: Rect) => void;\n onSmallDrag?: () => void;\n}): PointerEventHandlersWithLifecycle<EmbedPdfPointerEvent> {\n const { pageSize, scale, minDragPx = 5, onPreview, onCommit, onSmallDrag } = opts;\n\n let start: Position | null = null;\n let last: Rect | null = null;\n\n return {\n onPointerDown: (pos, evt) => {\n start = pos;\n last = { origin: { x: pos.x, y: pos.y }, size: { width: 0, height: 0 } };\n onPreview?.(last);\n evt.setPointerCapture?.();\n },\n onPointerMove: (pos) => {\n if (!start) return;\n const x = clamp(pos.x, 0, pageSize.width);\n const y = clamp(pos.y, 0, pageSize.height);\n last = {\n origin: { x: Math.min(start.x, x), y: Math.min(start.y, y) },\n size: { width: Math.abs(x - start.x), height: Math.abs(y - start.y) },\n };\n onPreview?.(last);\n },\n onPointerUp: (_pos, evt) => {\n if (last) {\n const dragPx = Math.max(last.size.width, last.size.height) * scale;\n if (dragPx > minDragPx) {\n onCommit?.(last); // Large drag → zoom to area\n } else {\n onSmallDrag?.(); // Small drag → zoom in\n }\n }\n start = null;\n last = null;\n onPreview?.(null);\n evt.releasePointerCapture?.();\n },\n onPointerCancel: (_pos, evt) => {\n start = null;\n last = null;\n onPreview?.(null);\n evt.releasePointerCapture?.();\n },\n };\n}\n","import { PluginPackage } from '@embedpdf/core';\n\nimport { ZoomAction } from './actions';\nimport { manifest, ZOOM_PLUGIN_ID } from './manifest';\nimport { zoomReducer, initialState, initialDocumentState } from './reducer';\nimport { ZoomPluginConfig, ZoomState } from './types';\nimport { ZoomPlugin } from './zoom-plugin';\n\nexport const ZoomPluginPackage: PluginPackage<ZoomPlugin, ZoomPluginConfig, ZoomState, ZoomAction> =\n {\n manifest,\n create: (registry, config) => new ZoomPlugin(ZOOM_PLUGIN_ID, registry, config),\n reducer: zoomReducer,\n initialState,\n };\n\nexport * from './zoom-plugin';\nexport * from './types';\nexport * from './manifest';\nexport { initialState, initialDocumentState };\n"],"names":["ZoomMode","VerticalZoomFocus","ZOOM_PLUGIN_ID","manifest","id","name","version","provides","requires","optional","defaultConfig","enabled","defaultZoomLevel","Automatic","minZoom","maxZoom","zoomStep","zoomRanges","min","max","step","presets","value","FitPage","FitWidth","INIT_ZOOM_STATE","CLEANUP_ZOOM_STATE","SET_ZOOM_LEVEL","SET_MARQUEE_ZOOM_ACTIVE","initialDocumentState","zoomLevel","currentZoomLevel","isMarqueeZoomActive","initialState","documents","activeDocumentId","_ZoomPlugin","BasePlugin","constructor","registry","cfg","super","this","zoom$","createEmitter","state$","createBehaviorEmitter","viewportPlugin","getPlugin","viewport","scroll","interactionManager","spread","normalizeRanges","onViewportResize","event","recalcAuto","documentId","Top","mode","wait","keyExtractor","_a","onSpreadChange","_b","registerMode","scope","exclusive","cursor","_c","onModeChange","state","isMarqueeActive","activeMode","docState","getDocumentState","dispatch","type","payload","isActive","onDocumentLoadingStarted","gate","initZoomState","logger","debug","onDocumentLoaded","onDocumentClosed","cleanupZoomState","onRotationChanged","buildCapability","requestZoom","level","c","requestZoomBy","d","zoomIn","zoomOut","zoomToArea","pageIndex","rect","enableMarqueeZoom","disableMarqueeZoom","toggleMarqueeZoom","getState","getDocumentStateOrThrow","forDocument","createZoomScope","registerMarqueeOnPage","opts","getPresets","onZoomChange","on","onStateChange","listener","getActiveDocumentId","Error","center","handleRequest","delta","cur","target","toZoom","stepFor","handleZoomToArea","activate","activateDefaultMode","getActiveMode","focus","Center","align","coreState","core","metrics","getMetrics","oldZoom","clientWidth","clientHeight","base","computeZoomForMode","exactZoom","clamp","newZoom","Math","floor","focusPoint","vx","vy","desiredScrollLeft","desiredScrollTop","computeScrollForZoomChange","isNaN","setViewportScrollMetrics","scrollLeft","scrollTop","setZoomLevel","dispatchCoreAction","setScale","isGated","releaseGate","scrollTo","x","y","behavior","evt","emit","vp","scrollScope","pgGap","getPageGap","vpGap","getViewportGap","spreads","getSpreadPagesWithRotatedSize","length","availableWidth","availableHeight","maxContentW","maxContentH","forEach","contentW","reduce","s","p","i","rotatedSize","width","contentH","map","height","layout","getLayout","totalContentSize","off","availableSpace","cw","zoom","offXold","offYold","offXnew","offYnew","baseLeft","baseTop","coreDoc","rotation","oldZ","availableW","availableH","vItem","virtualItems","find","it","pageLayouts","some","pageRel","rotatedRect","rotateRect","targetZoom","size","pageAbsX","pageAbsY","cxContent","origin","cyContent","avail","z","centerVX","centerVY","ranges","filter","r","sort","a","b","v","parseFloat","toFixed","warn","document","page","pages","handlers","pageSize","scale","minDragPx","onPreview","onCommit","onSmallDrag","start","last","onPointerDown","pos","setPointerCapture","call","onPointerMove","abs","onPointerUp","_pos","releasePointerCapture","onPointerCancel","createMarqueeHandler","callback","registerHandlers","modeId","onStoreUpdated","prevState","newState","prevDoc","newDoc","initialize","info","destroy","clear","ZoomPlugin","ZoomPluginPackage","create","config","reducer","action","removed","remainingDocs"],"mappings":"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"}
1
+ {"version":3,"file":"index.cjs","sources":["../src/lib/types.ts","../src/lib/manifest.ts","../src/lib/actions.ts","../src/lib/reducer.ts","../src/lib/zoom-plugin.ts","../src/lib/handlers/marquee-zoom.handler.ts","../src/lib/index.ts"],"sourcesContent":["import { BasePluginConfig, EventHook } from '@embedpdf/core';\nimport { Rect } from '@embedpdf/models';\nimport { ViewportMetrics } from '@embedpdf/plugin-viewport';\n\n/* ------------------------------------------------------------------ */\n/* public */\n/* ------------------------------------------------------------------ */\n\nexport enum ZoomMode {\n Automatic = 'automatic',\n FitPage = 'fit-page',\n FitWidth = 'fit-width',\n}\n\nexport type ZoomLevel = ZoomMode | number;\n\nexport interface Point {\n vx: number;\n vy: number;\n}\n\nexport interface ZoomChangeEvent {\n documentId: string;\n /** old and new *actual* scale factors */\n oldZoom: number;\n newZoom: number;\n /** level used to obtain the newZoom (number | mode) */\n level: ZoomLevel;\n /** viewport point kept under the finger / mouse‑wheel focus */\n center: Point;\n /** where the viewport should scroll to after the scale change */\n desiredScrollLeft: number;\n desiredScrollTop: number;\n /** metrics at the moment the zoom was requested */\n viewport: ViewportMetrics;\n}\n\nexport interface StateChangeEvent {\n documentId: string;\n state: ZoomDocumentState;\n}\n\nexport interface MarqueeZoomCallback {\n onPreview?: (rect: Rect | null) => void;\n onCommit?: (rect: Rect) => void;\n onSmallDrag?: () => void;\n}\n\nexport interface RegisterMarqueeOnPageOptions {\n documentId: string;\n pageIndex: number;\n scale: number;\n callback: MarqueeZoomCallback;\n}\n\n// Per-document zoom state\nexport interface ZoomDocumentState {\n zoomLevel: ZoomLevel; // last **requested** level\n currentZoomLevel: number; // actual numeric factor\n isMarqueeZoomActive: boolean; // whether marquee zoom mode is active\n}\n\n// Scoped zoom capability\nexport interface ZoomScope {\n requestZoom(level: ZoomLevel, center?: Point): void;\n requestZoomBy(delta: number, center?: Point): void;\n zoomIn(): void;\n zoomOut(): void;\n zoomToArea(pageIndex: number, rect: Rect): void;\n enableMarqueeZoom(): void;\n disableMarqueeZoom(): void;\n toggleMarqueeZoom(): void;\n isMarqueeZoomActive(): boolean;\n getState(): ZoomDocumentState;\n onZoomChange: EventHook<ZoomChangeEvent>;\n onStateChange: EventHook<ZoomDocumentState>;\n}\n\nexport interface ZoomCapability {\n // Active document operations\n requestZoom(level: ZoomLevel, center?: Point): void;\n requestZoomBy(delta: number, center?: Point): void;\n zoomIn(): void;\n zoomOut(): void;\n zoomToArea(pageIndex: number, rect: Rect): void;\n enableMarqueeZoom(): void;\n disableMarqueeZoom(): void;\n toggleMarqueeZoom(): void;\n isMarqueeZoomActive(): boolean;\n getState(): ZoomDocumentState;\n\n // Document-scoped operations\n forDocument(documentId: string): ZoomScope;\n\n // Global\n registerMarqueeOnPage: (opts: RegisterMarqueeOnPageOptions) => () => void;\n getPresets(): ZoomPreset[];\n\n // Events (include documentId)\n onZoomChange: EventHook<ZoomChangeEvent>;\n onStateChange: EventHook<StateChangeEvent>;\n}\n\n/* ------------------------------------------------------------------ */\n/* config / store */\n/* ------------------------------------------------------------------ */\n\nexport interface ZoomRangeStep {\n min: number;\n max: number;\n step: number;\n}\n\nexport interface ZoomPreset {\n name: string;\n value: ZoomLevel;\n icon?: string;\n}\n\nexport interface ZoomPluginConfig extends BasePluginConfig {\n defaultZoomLevel: ZoomLevel;\n minZoom?: number;\n maxZoom?: number;\n zoomStep?: number;\n zoomRanges?: ZoomRangeStep[];\n presets?: ZoomPreset[];\n}\n\nexport interface ZoomState {\n // Per-document zoom state\n documents: Record<string, ZoomDocumentState>;\n activeDocumentId: string | null;\n}\n\nexport enum VerticalZoomFocus {\n Center,\n Top,\n}\n\nexport interface ZoomRequest {\n level: ZoomLevel;\n delta?: number;\n center?: Point;\n focus?: VerticalZoomFocus;\n align?: 'keep' | 'center';\n}\n","import { PluginManifest } from '@embedpdf/core';\n\nimport { ZoomMode, ZoomPluginConfig } from './types';\n\nexport const ZOOM_PLUGIN_ID = 'zoom';\n\nexport const manifest: PluginManifest<ZoomPluginConfig> = {\n id: ZOOM_PLUGIN_ID,\n name: 'Zoom Plugin',\n version: '1.0.0',\n provides: ['zoom'],\n requires: ['viewport', 'scroll'],\n optional: ['interaction-manager', 'spread'],\n defaultConfig: {\n defaultZoomLevel: ZoomMode.Automatic,\n minZoom: 0.2,\n maxZoom: 60,\n zoomStep: 0.1,\n zoomRanges: [\n {\n min: 0.2,\n max: 0.5,\n step: 0.05,\n },\n {\n min: 0.5,\n max: 1.0,\n step: 0.1,\n },\n {\n min: 1.0,\n max: 2.0,\n step: 0.2,\n },\n {\n min: 2.0,\n max: 4.0,\n step: 0.4,\n },\n {\n min: 4.0,\n max: 10.0,\n step: 0.8,\n },\n {\n min: 10.0,\n max: 20.0,\n step: 1.6,\n },\n {\n min: 20.0,\n max: 40.0,\n step: 3.2,\n },\n {\n min: 40.0,\n max: 60.0,\n step: 6.4,\n },\n ],\n presets: [\n {\n name: 'Fit Page',\n value: ZoomMode.FitPage,\n },\n {\n name: 'Fit Width',\n value: ZoomMode.FitWidth,\n },\n {\n name: 'Automatic',\n value: ZoomMode.Automatic,\n },\n {\n name: '25%',\n value: 0.25,\n },\n {\n name: '50%',\n value: 0.5,\n },\n {\n name: '100%',\n value: 1,\n },\n {\n name: '125%',\n value: 1.25,\n },\n {\n name: '150%',\n value: 1.5,\n },\n {\n name: '200%',\n value: 2,\n },\n {\n name: '400%',\n value: 4,\n },\n {\n name: '800%',\n value: 8,\n },\n {\n name: '1600%',\n value: 16,\n },\n ],\n },\n};\n","import { Action } from '@embedpdf/core';\nimport { ZoomLevel, ZoomDocumentState } from './types';\n\n// Document lifecycle\nexport const INIT_ZOOM_STATE = 'ZOOM/INIT_STATE';\nexport const CLEANUP_ZOOM_STATE = 'ZOOM/CLEANUP_STATE';\nexport const SET_ACTIVE_DOCUMENT = 'ZOOM/SET_ACTIVE_DOCUMENT';\n\n// Per-document actions\nexport const SET_ZOOM_LEVEL = 'ZOOM/SET_ZOOM_LEVEL';\nexport const SET_MARQUEE_ZOOM_ACTIVE = 'ZOOM/SET_MARQUEE_ZOOM_ACTIVE';\n\n// Document lifecycle actions\nexport interface InitZoomStateAction extends Action {\n type: typeof INIT_ZOOM_STATE;\n payload: {\n documentId: string;\n state: ZoomDocumentState;\n };\n}\n\nexport interface CleanupZoomStateAction extends Action {\n type: typeof CLEANUP_ZOOM_STATE;\n payload: string; // documentId\n}\n\nexport interface SetActiveDocumentAction extends Action {\n type: typeof SET_ACTIVE_DOCUMENT;\n payload: string | null; // documentId\n}\n\nexport interface SetZoomLevelAction extends Action {\n type: typeof SET_ZOOM_LEVEL;\n payload: {\n documentId: string;\n zoomLevel: ZoomLevel;\n currentZoomLevel: number;\n };\n}\n\nexport interface SetMarqueeZoomActiveAction extends Action {\n type: typeof SET_MARQUEE_ZOOM_ACTIVE;\n payload: {\n documentId: string;\n isActive: boolean;\n };\n}\n\nexport type ZoomAction =\n | InitZoomStateAction\n | CleanupZoomStateAction\n | SetActiveDocumentAction\n | SetZoomLevelAction\n | SetMarqueeZoomActiveAction;\n\n// Action Creators\nexport function initZoomState(documentId: string, state: ZoomDocumentState): InitZoomStateAction {\n return { type: INIT_ZOOM_STATE, payload: { documentId, state } };\n}\n\nexport function cleanupZoomState(documentId: string): CleanupZoomStateAction {\n return { type: CLEANUP_ZOOM_STATE, payload: documentId };\n}\n\nexport function setActiveDocument(documentId: string | null): SetActiveDocumentAction {\n return { type: SET_ACTIVE_DOCUMENT, payload: documentId };\n}\n\nexport function setZoomLevel(\n documentId: string,\n zoomLevel: ZoomLevel,\n currentZoomLevel: number,\n): SetZoomLevelAction {\n return { type: SET_ZOOM_LEVEL, payload: { documentId, zoomLevel, currentZoomLevel } };\n}\n\nexport function setMarqueeZoomActive(\n documentId: string,\n isActive: boolean,\n): SetMarqueeZoomActiveAction {\n return { type: SET_MARQUEE_ZOOM_ACTIVE, payload: { documentId, isActive } };\n}\n","import { Reducer } from '@embedpdf/core';\nimport {\n ZoomAction,\n INIT_ZOOM_STATE,\n CLEANUP_ZOOM_STATE,\n SET_ACTIVE_DOCUMENT,\n SET_ZOOM_LEVEL,\n SET_MARQUEE_ZOOM_ACTIVE,\n} from './actions';\nimport { ZoomState, ZoomDocumentState, ZoomMode } from './types';\n\nexport const initialDocumentState: ZoomDocumentState = {\n zoomLevel: ZoomMode.Automatic,\n currentZoomLevel: 1,\n isMarqueeZoomActive: false,\n};\n\nexport const initialState: ZoomState = {\n documents: {},\n activeDocumentId: null,\n};\n\nexport const zoomReducer: Reducer<ZoomState, ZoomAction> = (state = initialState, action) => {\n switch (action.type) {\n case INIT_ZOOM_STATE: {\n const { documentId, state: docState } = action.payload;\n return {\n ...state,\n documents: {\n ...state.documents,\n [documentId]: docState,\n },\n // Set as active if no active document\n activeDocumentId: state.activeDocumentId ?? documentId,\n };\n }\n\n case CLEANUP_ZOOM_STATE: {\n const documentId = action.payload;\n const { [documentId]: removed, ...remainingDocs } = state.documents;\n return {\n ...state,\n documents: remainingDocs,\n activeDocumentId: state.activeDocumentId === documentId ? null : state.activeDocumentId,\n };\n }\n\n case SET_ACTIVE_DOCUMENT: {\n return {\n ...state,\n activeDocumentId: action.payload,\n };\n }\n\n case SET_ZOOM_LEVEL: {\n const { documentId, zoomLevel, currentZoomLevel } = action.payload;\n const docState = state.documents[documentId];\n if (!docState) return state;\n\n return {\n ...state,\n documents: {\n ...state.documents,\n [documentId]: {\n ...docState,\n zoomLevel,\n currentZoomLevel,\n },\n },\n };\n }\n\n case SET_MARQUEE_ZOOM_ACTIVE: {\n const { documentId, isActive } = action.payload;\n const docState = state.documents[documentId];\n if (!docState) return state;\n\n return {\n ...state,\n documents: {\n ...state.documents,\n [documentId]: {\n ...docState,\n isMarqueeZoomActive: isActive,\n },\n },\n };\n }\n\n default:\n return state;\n }\n};\n","import {\n BasePlugin,\n PluginRegistry,\n createEmitter,\n clamp,\n setScale,\n createBehaviorEmitter,\n Listener,\n} from '@embedpdf/core';\nimport { ScrollPlugin, ScrollCapability } from '@embedpdf/plugin-scroll';\nimport { ViewportPlugin, ViewportCapability, ViewportMetrics } from '@embedpdf/plugin-viewport';\n\nimport {\n initZoomState,\n cleanupZoomState,\n setZoomLevel,\n ZoomAction,\n setMarqueeZoomActive,\n} from './actions';\nimport {\n ZoomPluginConfig,\n ZoomState,\n ZoomMode,\n Point,\n ZoomChangeEvent,\n ZoomCapability,\n ZoomPreset,\n ZoomRangeStep,\n VerticalZoomFocus,\n ZoomRequest,\n RegisterMarqueeOnPageOptions,\n ZoomScope,\n StateChangeEvent,\n ZoomDocumentState,\n} from './types';\nimport {\n InteractionManagerCapability,\n InteractionManagerPlugin,\n} from '@embedpdf/plugin-interaction-manager';\nimport { SpreadCapability, SpreadPlugin } from '@embedpdf/plugin-spread';\nimport { Rect, rotateRect } from '@embedpdf/models';\nimport { createMarqueeHandler } from './handlers';\nimport { initialDocumentState } from './reducer';\n\nexport class ZoomPlugin extends BasePlugin<\n ZoomPluginConfig,\n ZoomCapability,\n ZoomState,\n ZoomAction\n> {\n static readonly id = 'zoom' as const;\n\n private readonly zoom$ = createEmitter<ZoomChangeEvent>();\n private readonly state$ = createBehaviorEmitter<StateChangeEvent>();\n private readonly viewport: ViewportCapability;\n private readonly viewportPlugin: ViewportPlugin;\n private readonly scroll: ScrollCapability;\n private readonly interactionManager: InteractionManagerCapability | null;\n private readonly spread: SpreadCapability | null;\n private readonly presets: ZoomPreset[];\n private readonly zoomRanges: ZoomRangeStep[];\n private readonly defaultZoomLevel: ZoomMode | number;\n\n private readonly minZoom: number;\n private readonly maxZoom: number;\n private readonly zoomStep: number;\n\n constructor(id: string, registry: PluginRegistry, cfg: ZoomPluginConfig) {\n super(id, registry);\n\n this.viewportPlugin = registry.getPlugin<ViewportPlugin>('viewport')!;\n this.viewport = this.viewportPlugin.provides();\n this.scroll = registry.getPlugin<ScrollPlugin>('scroll')!.provides();\n const interactionManager = registry.getPlugin<InteractionManagerPlugin>('interaction-manager');\n this.interactionManager = interactionManager?.provides() ?? null;\n const spread = registry.getPlugin<SpreadPlugin>('spread');\n this.spread = spread?.provides() ?? null;\n\n this.minZoom = cfg.minZoom ?? 0.25;\n this.maxZoom = cfg.maxZoom ?? 10;\n this.zoomStep = cfg.zoomStep ?? 0.1;\n this.defaultZoomLevel = cfg.defaultZoomLevel;\n this.presets = cfg.presets ?? [];\n this.zoomRanges = this.normalizeRanges(cfg.zoomRanges ?? []);\n\n // Keep automatic modes up to date per document\n this.viewport.onViewportResize(\n (event) => this.recalcAuto(event.documentId, VerticalZoomFocus.Top),\n {\n mode: 'debounce',\n wait: 150,\n keyExtractor: (event) => event.documentId,\n },\n );\n\n // Subscribe to spread changes\n this.spread?.onSpreadChange((event) => {\n this.recalcAuto(event.documentId, VerticalZoomFocus.Top);\n });\n\n // Register marquee zoom mode\n this.interactionManager?.registerMode({\n id: 'marqueeZoom',\n scope: 'page',\n exclusive: true,\n cursor: 'zoom-in',\n });\n\n this.interactionManager?.onModeChange((state) => {\n // Track marquee zoom state changes for this document\n const isMarqueeActive = state.activeMode === 'marqueeZoom';\n const docState = this.getDocumentState(state.documentId);\n\n // Only dispatch if state actually changed\n if (docState && docState.isMarqueeZoomActive !== isMarqueeActive) {\n this.dispatch(setMarqueeZoomActive(state.documentId, isMarqueeActive));\n }\n });\n }\n\n // ─────────────────────────────────────────────────────────\n // Document Lifecycle Hooks (from BasePlugin)\n // ─────────────────────────────────────────────────────────\n\n protected override onDocumentLoadingStarted(documentId: string): void {\n this.viewport.gate('zoom', documentId);\n // Initialize zoom state for this document\n const docState: ZoomDocumentState = {\n ...initialDocumentState,\n zoomLevel: this.defaultZoomLevel,\n };\n\n this.dispatch(initZoomState(documentId, docState));\n\n this.logger.debug(\n 'ZoomPlugin',\n 'DocumentOpened',\n `Initialized zoom state for document: ${documentId}`,\n );\n }\n\n protected override onDocumentLoaded(documentId: string): void {\n // Apply initial zoom after document is fully loaded\n this.recalcAuto(documentId, VerticalZoomFocus.Top);\n }\n\n protected override onDocumentClosed(documentId: string): void {\n this.dispatch(cleanupZoomState(documentId));\n\n this.logger.debug(\n 'ZoomPlugin',\n 'DocumentClosed',\n `Cleaned up zoom state for document: ${documentId}`,\n );\n }\n\n protected override onRotationChanged(documentId: string): void {\n // Recalculate auto modes when rotation changes\n this.recalcAuto(documentId, VerticalZoomFocus.Top);\n }\n\n /*\n protected override onPagesChanged(documentId: string): void {\n // Recalculate auto modes when pages change\n this.recalcAuto(documentId, VerticalZoomFocus.Top);\n }*/\n\n // ─────────────────────────────────────────────────────────\n // Capability\n // ─────────────────────────────────────────────────────────\n\n protected buildCapability(): ZoomCapability {\n return {\n // Active document operations\n requestZoom: (level, c) => this.requestZoom(level, c),\n requestZoomBy: (d, c) => this.requestZoomBy(d, c),\n zoomIn: () => this.zoomIn(),\n zoomOut: () => this.zoomOut(),\n zoomToArea: (pageIndex, rect) => this.zoomToArea(pageIndex, rect),\n enableMarqueeZoom: () => this.enableMarqueeZoom(),\n disableMarqueeZoom: () => this.disableMarqueeZoom(),\n toggleMarqueeZoom: () => this.toggleMarqueeZoom(),\n isMarqueeZoomActive: () => this.isMarqueeZoomActive(),\n getState: () => this.getDocumentStateOrThrow(),\n\n // Document-scoped operations\n forDocument: (documentId: string) => this.createZoomScope(documentId),\n\n // Global\n registerMarqueeOnPage: (opts) => this.registerMarqueeOnPage(opts),\n getPresets: () => this.presets,\n\n // Events\n onZoomChange: this.zoom$.on,\n onStateChange: this.state$.on,\n };\n }\n\n // ─────────────────────────────────────────────────────────\n // Document Scoping\n // ─────────────────────────────────────────────────────────\n\n private createZoomScope(documentId: string): ZoomScope {\n return {\n requestZoom: (level, c) => this.requestZoom(level, c, documentId),\n requestZoomBy: (d, c) => this.requestZoomBy(d, c, documentId),\n zoomIn: () => this.zoomIn(documentId),\n zoomOut: () => this.zoomOut(documentId),\n zoomToArea: (pageIndex, rect) => this.zoomToArea(pageIndex, rect, documentId),\n enableMarqueeZoom: () => this.enableMarqueeZoom(documentId),\n disableMarqueeZoom: () => this.disableMarqueeZoom(documentId),\n toggleMarqueeZoom: () => this.toggleMarqueeZoom(documentId),\n isMarqueeZoomActive: () => this.isMarqueeZoomActive(documentId),\n getState: () => this.getDocumentStateOrThrow(documentId),\n onZoomChange: (listener: Listener<ZoomChangeEvent>) =>\n this.zoom$.on((event) => {\n if (event.documentId === documentId) listener(event);\n }),\n onStateChange: (listener: Listener<ZoomDocumentState>) =>\n this.state$.on((event) => {\n if (event.documentId === documentId) listener(event.state);\n }),\n };\n }\n\n // ─────────────────────────────────────────────────────────\n // State Helpers\n // ─────────────────────────────────────────────────────────\n\n private getDocumentState(documentId?: string): ZoomDocumentState | null {\n const id = documentId ?? this.getActiveDocumentId();\n return this.state.documents[id] ?? null;\n }\n\n private getDocumentStateOrThrow(documentId?: string): ZoomDocumentState {\n const state = this.getDocumentState(documentId);\n if (!state) {\n throw new Error(`Zoom state not found for document: ${documentId ?? 'active'}`);\n }\n return state;\n }\n\n // ─────────────────────────────────────────────────────────\n // Core Operations\n // ─────────────────────────────────────────────────────────\n\n private requestZoom(level: ZoomMode | number, center?: Point, documentId?: string): void {\n this.handleRequest({ level, center }, documentId);\n }\n\n private requestZoomBy(delta: number, center?: Point, documentId?: string): void {\n const id = documentId ?? this.getActiveDocumentId();\n const docState = this.getDocumentStateOrThrow(id);\n const cur = docState.currentZoomLevel;\n const target = this.toZoom(cur + delta);\n this.handleRequest({ level: target, center }, id);\n }\n\n private zoomIn(documentId?: string): void {\n const id = documentId ?? this.getActiveDocumentId();\n const docState = this.getDocumentStateOrThrow(id);\n const cur = docState.currentZoomLevel;\n this.handleRequest({ level: cur, delta: this.stepFor(cur) }, id);\n }\n\n private zoomOut(documentId?: string): void {\n const id = documentId ?? this.getActiveDocumentId();\n const docState = this.getDocumentStateOrThrow(id);\n const cur = docState.currentZoomLevel;\n this.handleRequest({ level: cur, delta: -this.stepFor(cur) }, id);\n }\n\n private zoomToArea(pageIndex: number, rect: Rect, documentId?: string): void {\n const id = documentId ?? this.getActiveDocumentId();\n this.handleZoomToArea(id, pageIndex, rect);\n }\n\n private enableMarqueeZoom(documentId?: string): void {\n const id = documentId ?? this.getActiveDocumentId();\n this.interactionManager?.forDocument(id).activate('marqueeZoom');\n }\n\n private disableMarqueeZoom(documentId?: string): void {\n const id = documentId ?? this.getActiveDocumentId();\n this.interactionManager?.forDocument(id).activateDefaultMode();\n }\n\n private toggleMarqueeZoom(documentId?: string): void {\n const id = documentId ?? this.getActiveDocumentId();\n const scope = this.interactionManager?.forDocument(id);\n if (scope?.getActiveMode() === 'marqueeZoom') {\n scope.activateDefaultMode();\n } else {\n scope?.activate('marqueeZoom');\n }\n }\n\n private isMarqueeZoomActive(documentId?: string): boolean {\n const id = documentId ?? this.getActiveDocumentId();\n return this.interactionManager?.forDocument(id).getActiveMode() === 'marqueeZoom';\n }\n\n // ─────────────────────────────────────────────────────────\n // Main Zoom Logic\n // ─────────────────────────────────────────────────────────\n\n private handleRequest(\n { level, delta = 0, center, focus = VerticalZoomFocus.Center, align = 'keep' }: ZoomRequest,\n documentId?: string,\n ) {\n const id = documentId ?? this.getActiveDocumentId();\n const docState = this.getDocumentStateOrThrow(id);\n const coreDoc = this.coreState.core.documents[id];\n if (!coreDoc) return;\n\n const viewport = this.viewport.forDocument(id);\n const metrics = viewport.getMetrics();\n const oldZoom = docState.currentZoomLevel;\n\n if (metrics.clientWidth === 0 || metrics.clientHeight === 0) {\n return;\n }\n\n // Step 1: Resolve target numeric zoom\n const base = typeof level === 'number' ? level : this.computeZoomForMode(id, level, metrics);\n\n if (base === false) return;\n\n const exactZoom = clamp(base + delta, this.minZoom, this.maxZoom);\n const newZoom = Math.floor(exactZoom * 1000) / 1000;\n\n // Step 2: Figure out viewport point to keep under focus\n const focusPoint: Point = center ?? {\n vx: metrics.clientWidth / 2,\n vy: focus === VerticalZoomFocus.Top ? 0 : metrics.clientHeight / 2,\n };\n\n // Step 3: Compute desired scroll offsets\n const { desiredScrollLeft, desiredScrollTop } = this.computeScrollForZoomChange(\n id,\n metrics,\n oldZoom,\n newZoom,\n focusPoint,\n align,\n );\n\n // Step 4: Dispatch and notify\n if (!isNaN(desiredScrollLeft) && !isNaN(desiredScrollTop)) {\n this.viewportPlugin.setViewportScrollMetrics(id, {\n scrollLeft: desiredScrollLeft,\n scrollTop: desiredScrollTop,\n });\n }\n\n this.dispatch(setZoomLevel(id, typeof level === 'number' ? newZoom : level, newZoom));\n this.dispatchCoreAction(setScale(newZoom, id));\n if (this.viewport.isGated(id)) {\n this.viewport.releaseGate('zoom', id);\n }\n\n viewport.scrollTo({\n x: desiredScrollLeft,\n y: desiredScrollTop,\n behavior: 'instant',\n });\n\n const evt: ZoomChangeEvent = {\n documentId: id,\n oldZoom,\n newZoom,\n level,\n center: focusPoint,\n desiredScrollLeft,\n desiredScrollTop,\n viewport: metrics,\n };\n\n this.zoom$.emit(evt);\n }\n\n private computeZoomForMode(\n documentId: string,\n mode: ZoomMode,\n vp: ViewportMetrics,\n ): number | false {\n const coreDoc = this.coreState.core.documents[documentId];\n if (!coreDoc) return false;\n\n const scrollScope = this.scroll.forDocument(documentId);\n const pgGap = scrollScope ? this.scroll.getPageGap() : 0;\n const vpGap = this.viewport.getViewportGap();\n\n const spreads = scrollScope.getSpreadPagesWithRotatedSize();\n if (!spreads.length) return false;\n\n if (vp.clientWidth === 0 || vp.clientHeight === 0) return false;\n\n const availableWidth = vp.clientWidth - 2 * vpGap;\n const availableHeight = vp.clientHeight - 2 * vpGap;\n\n if (availableWidth <= 0 || availableHeight <= 0) return false;\n\n let maxContentW = 0,\n maxContentH = 0;\n\n spreads.forEach((spread) => {\n const contentW = spread.reduce((s, p, i) => s + p.rotatedSize.width + (i ? pgGap : 0), 0);\n const contentH = Math.max(...spread.map((p) => p.rotatedSize.height));\n maxContentW = Math.max(maxContentW, contentW);\n maxContentH = Math.max(maxContentH, contentH);\n });\n\n switch (mode) {\n case ZoomMode.FitWidth:\n return availableWidth / maxContentW;\n case ZoomMode.FitPage:\n return Math.min(availableWidth / maxContentW, availableHeight / maxContentH);\n case ZoomMode.Automatic:\n return Math.min(availableWidth / maxContentW, 1);\n default:\n return 1;\n }\n }\n\n private computeScrollForZoomChange(\n documentId: string,\n vp: ViewportMetrics,\n oldZoom: number,\n newZoom: number,\n focus: Point,\n align: 'keep' | 'center' = 'keep',\n ) {\n const scrollScope = this.scroll.forDocument(documentId);\n const layout = scrollScope.getLayout();\n const vpGap = this.viewport.getViewportGap();\n\n const contentW = layout.totalContentSize.width;\n const contentH = layout.totalContentSize.height;\n\n const availableWidth = vp.clientWidth - 2 * vpGap;\n const availableHeight = vp.clientHeight - 2 * vpGap;\n\n const off = (availableSpace: number, cw: number, zoom: number) =>\n cw * zoom < availableSpace ? (availableSpace - cw * zoom) / 2 : 0;\n\n const offXold = off(availableWidth, contentW, oldZoom);\n const offYold = off(availableHeight, contentH, oldZoom);\n\n const offXnew = off(availableWidth, contentW, newZoom);\n const offYnew = off(availableHeight, contentH, newZoom);\n\n const cx = (vp.scrollLeft + focus.vx - vpGap - offXold) / oldZoom;\n const cy = (vp.scrollTop + focus.vy - vpGap - offYold) / oldZoom;\n\n const baseLeft = cx * newZoom + vpGap + offXnew;\n const baseTop = cy * newZoom + vpGap + offYnew;\n\n const desiredScrollLeft =\n align === 'center' ? baseLeft - vp.clientWidth / 2 : baseLeft - focus.vx;\n const desiredScrollTop =\n align === 'center' ? baseTop - vp.clientHeight / 2 : baseTop - focus.vy;\n\n return {\n desiredScrollLeft: Math.max(0, desiredScrollLeft),\n desiredScrollTop: Math.max(0, desiredScrollTop),\n };\n }\n\n private handleZoomToArea(documentId: string, pageIndex: number, rect: Rect) {\n const coreDoc = this.coreState.core.documents[documentId];\n if (!coreDoc) return;\n\n const rotation = coreDoc.rotation;\n const viewport = this.viewport.forDocument(documentId);\n const vp = viewport.getMetrics();\n const vpGap = this.viewport.getViewportGap();\n const docState = this.getDocumentStateOrThrow(documentId);\n const oldZ = docState.currentZoomLevel;\n\n const availableW = vp.clientWidth - 2 * vpGap;\n const availableH = vp.clientHeight - 2 * vpGap;\n\n const scrollScope = this.scroll.forDocument(documentId);\n const layout = scrollScope.getLayout();\n\n const vItem = layout.virtualItems.find((it) =>\n it.pageLayouts.some((p) => p.pageIndex === pageIndex),\n );\n if (!vItem) return;\n\n const pageRel = vItem.pageLayouts.find((p) => p.pageIndex === pageIndex)!;\n\n const rotatedRect = rotateRect(\n { width: pageRel.width, height: pageRel.height },\n rect,\n rotation,\n );\n\n const targetZoom = this.toZoom(\n Math.min(availableW / rotatedRect.size.width, availableH / rotatedRect.size.height),\n );\n\n const pageAbsX = vItem.x + pageRel.x;\n const pageAbsY = vItem.y + pageRel.y;\n\n const cxContent = pageAbsX + rotatedRect.origin.x + rotatedRect.size.width / 2;\n const cyContent = pageAbsY + rotatedRect.origin.y + rotatedRect.size.height / 2;\n\n const off = (avail: number, cw: number, z: number) =>\n cw * z < avail ? (avail - cw * z) / 2 : 0;\n\n const offXold = off(availableW, layout.totalContentSize.width, oldZ);\n const offYold = off(availableH, layout.totalContentSize.height, oldZ);\n\n const centerVX = vpGap + offXold + cxContent * oldZ - vp.scrollLeft;\n const centerVY = vpGap + offYold + cyContent * oldZ - vp.scrollTop;\n\n this.handleRequest(\n {\n level: targetZoom,\n center: { vx: centerVX, vy: centerVY },\n align: 'center',\n },\n documentId,\n );\n }\n\n private recalcAuto(documentId: string, focus?: VerticalZoomFocus) {\n const docState = this.getDocumentState(documentId);\n if (!docState) return;\n\n if (\n docState.zoomLevel === ZoomMode.Automatic ||\n docState.zoomLevel === ZoomMode.FitPage ||\n docState.zoomLevel === ZoomMode.FitWidth\n ) {\n this.handleRequest({ level: docState.zoomLevel, focus }, documentId);\n }\n }\n\n // ─────────────────────────────────────────────────────────\n // Helpers\n // ─────────────────────────────────────────────────────────\n\n private normalizeRanges(ranges: ZoomRangeStep[]): ZoomRangeStep[] {\n return [...ranges].filter((r) => r.step > 0 && r.max > r.min).sort((a, b) => a.min - b.min);\n }\n\n private stepFor(zoom: number): number {\n const r = this.zoomRanges.find((r) => zoom >= r.min && zoom < r.max);\n return r ? r.step : this.zoomStep;\n }\n\n private toZoom(v: number) {\n return parseFloat(clamp(v, this.minZoom, this.maxZoom).toFixed(2));\n }\n\n // ─────────────────────────────────────────────────────────\n // Marquee Zoom\n // ─────────────────────────────────────────────────────────\n\n public registerMarqueeOnPage(opts: RegisterMarqueeOnPageOptions) {\n if (!this.interactionManager) {\n this.logger.warn(\n 'ZoomPlugin',\n 'MissingDependency',\n 'Interaction manager plugin not loaded, marquee zoom disabled',\n );\n return () => {};\n }\n\n const coreDoc = this.coreState.core.documents[opts.documentId];\n if (!coreDoc || !coreDoc.document) {\n this.logger.warn('ZoomPlugin', 'DocumentNotFound', 'Document not found');\n return () => {};\n }\n\n const page = coreDoc.document.pages[opts.pageIndex];\n if (!page) {\n this.logger.warn('ZoomPlugin', 'PageNotFound', `Page ${opts.pageIndex} not found`);\n return () => {};\n }\n\n const handlers = createMarqueeHandler({\n pageSize: page.size,\n scale: opts.scale,\n onPreview: opts.callback.onPreview,\n onCommit: (rect) => {\n this.zoomToArea(opts.pageIndex, rect, opts.documentId);\n opts.callback.onCommit?.(rect);\n },\n onSmallDrag: () => {\n this.zoomIn(opts.documentId);\n opts.callback.onSmallDrag?.();\n },\n });\n\n const off = this.interactionManager.registerHandlers({\n documentId: opts.documentId,\n modeId: 'marqueeZoom',\n handlers,\n pageIndex: opts.pageIndex,\n });\n\n return off;\n }\n\n // ─────────────────────────────────────────────────────────\n // Store Update Handlers\n // ─────────────────────────────────────────────────────────\n\n override onStoreUpdated(prevState: ZoomState, newState: ZoomState): void {\n // Emit state changes for each changed document\n for (const documentId in newState.documents) {\n const prevDoc = prevState.documents[documentId];\n const newDoc = newState.documents[documentId];\n\n if (\n prevDoc &&\n newDoc &&\n (prevDoc.currentZoomLevel !== newDoc.currentZoomLevel ||\n prevDoc.zoomLevel !== newDoc.zoomLevel ||\n prevDoc.isMarqueeZoomActive !== newDoc.isMarqueeZoomActive)\n ) {\n this.state$.emit({\n documentId,\n state: newDoc,\n });\n }\n }\n }\n\n // ─────────────────────────────────────────────────────────\n // Lifecycle\n // ─────────────────────────────────────────────────────────\n\n async initialize(): Promise<void> {\n this.logger.info('ZoomPlugin', 'Initialize', 'Zoom plugin initialized');\n }\n\n async destroy() {\n this.zoom$.clear();\n this.state$.clear();\n super.destroy();\n }\n}\n","import { Position, Rect, Size } from '@embedpdf/models';\nimport { clamp } from '@embedpdf/core';\nimport {\n EmbedPdfPointerEvent,\n PointerEventHandlersWithLifecycle,\n} from '@embedpdf/plugin-interaction-manager';\n\nexport function createMarqueeHandler(opts: {\n pageSize: Size;\n scale: number;\n minDragPx?: number;\n onPreview?: (rect: Rect | null) => void;\n onCommit?: (rect: Rect) => void;\n onSmallDrag?: () => void;\n}): PointerEventHandlersWithLifecycle<EmbedPdfPointerEvent> {\n const { pageSize, scale, minDragPx = 5, onPreview, onCommit, onSmallDrag } = opts;\n\n let start: Position | null = null;\n let last: Rect | null = null;\n\n return {\n onPointerDown: (pos, evt) => {\n start = pos;\n last = { origin: { x: pos.x, y: pos.y }, size: { width: 0, height: 0 } };\n onPreview?.(last);\n evt.setPointerCapture?.();\n },\n onPointerMove: (pos) => {\n if (!start) return;\n const x = clamp(pos.x, 0, pageSize.width);\n const y = clamp(pos.y, 0, pageSize.height);\n last = {\n origin: { x: Math.min(start.x, x), y: Math.min(start.y, y) },\n size: { width: Math.abs(x - start.x), height: Math.abs(y - start.y) },\n };\n onPreview?.(last);\n },\n onPointerUp: (_pos, evt) => {\n if (last) {\n const dragPx = Math.max(last.size.width, last.size.height) * scale;\n if (dragPx > minDragPx) {\n onCommit?.(last); // Large drag → zoom to area\n } else {\n onSmallDrag?.(); // Small drag → zoom in\n }\n }\n start = null;\n last = null;\n onPreview?.(null);\n evt.releasePointerCapture?.();\n },\n onPointerCancel: (_pos, evt) => {\n start = null;\n last = null;\n onPreview?.(null);\n evt.releasePointerCapture?.();\n },\n };\n}\n","import { PluginPackage } from '@embedpdf/core';\n\nimport { ZoomAction } from './actions';\nimport { manifest, ZOOM_PLUGIN_ID } from './manifest';\nimport { zoomReducer, initialState, initialDocumentState } from './reducer';\nimport { ZoomPluginConfig, ZoomState } from './types';\nimport { ZoomPlugin } from './zoom-plugin';\n\nexport const ZoomPluginPackage: PluginPackage<ZoomPlugin, ZoomPluginConfig, ZoomState, ZoomAction> =\n {\n manifest,\n create: (registry, config) => new ZoomPlugin(ZOOM_PLUGIN_ID, registry, config),\n reducer: zoomReducer,\n initialState,\n };\n\nexport * from './zoom-plugin';\nexport * from './types';\nexport * from './manifest';\nexport { initialState, initialDocumentState };\n"],"names":["ZoomMode","VerticalZoomFocus","ZOOM_PLUGIN_ID","manifest","id","name","version","provides","requires","optional","defaultConfig","defaultZoomLevel","Automatic","minZoom","maxZoom","zoomStep","zoomRanges","min","max","step","presets","value","FitPage","FitWidth","INIT_ZOOM_STATE","CLEANUP_ZOOM_STATE","SET_ZOOM_LEVEL","SET_MARQUEE_ZOOM_ACTIVE","initialDocumentState","zoomLevel","currentZoomLevel","isMarqueeZoomActive","initialState","documents","activeDocumentId","_ZoomPlugin","BasePlugin","constructor","registry","cfg","super","this","zoom$","createEmitter","state$","createBehaviorEmitter","viewportPlugin","getPlugin","viewport","scroll","interactionManager","spread","normalizeRanges","onViewportResize","event","recalcAuto","documentId","Top","mode","wait","keyExtractor","_a","onSpreadChange","_b","registerMode","scope","exclusive","cursor","_c","onModeChange","state","isMarqueeActive","activeMode","docState","getDocumentState","dispatch","type","payload","isActive","onDocumentLoadingStarted","gate","initZoomState","logger","debug","onDocumentLoaded","onDocumentClosed","cleanupZoomState","onRotationChanged","buildCapability","requestZoom","level","c","requestZoomBy","d","zoomIn","zoomOut","zoomToArea","pageIndex","rect","enableMarqueeZoom","disableMarqueeZoom","toggleMarqueeZoom","getState","getDocumentStateOrThrow","forDocument","createZoomScope","registerMarqueeOnPage","opts","getPresets","onZoomChange","on","onStateChange","listener","getActiveDocumentId","Error","center","handleRequest","delta","cur","target","toZoom","stepFor","handleZoomToArea","activate","activateDefaultMode","getActiveMode","focus","Center","align","coreState","core","metrics","getMetrics","oldZoom","clientWidth","clientHeight","base","computeZoomForMode","exactZoom","clamp","newZoom","Math","floor","focusPoint","vx","vy","desiredScrollLeft","desiredScrollTop","computeScrollForZoomChange","isNaN","setViewportScrollMetrics","scrollLeft","scrollTop","setZoomLevel","dispatchCoreAction","setScale","isGated","releaseGate","scrollTo","x","y","behavior","evt","emit","vp","scrollScope","pgGap","getPageGap","vpGap","getViewportGap","spreads","getSpreadPagesWithRotatedSize","length","availableWidth","availableHeight","maxContentW","maxContentH","forEach","contentW","reduce","s","p","i","rotatedSize","width","contentH","map","height","layout","getLayout","totalContentSize","off","availableSpace","cw","zoom","offXold","offYold","offXnew","offYnew","baseLeft","baseTop","coreDoc","rotation","oldZ","availableW","availableH","vItem","virtualItems","find","it","pageLayouts","some","pageRel","rotatedRect","rotateRect","targetZoom","size","pageAbsX","pageAbsY","cxContent","origin","cyContent","avail","z","centerVX","centerVY","ranges","filter","r","sort","a","b","v","parseFloat","toFixed","warn","document","page","pages","handlers","pageSize","scale","minDragPx","onPreview","onCommit","onSmallDrag","start","last","onPointerDown","pos","setPointerCapture","call","onPointerMove","abs","onPointerUp","_pos","releasePointerCapture","onPointerCancel","createMarqueeHandler","callback","registerHandlers","modeId","onStoreUpdated","prevState","newState","prevDoc","newDoc","initialize","info","destroy","clear","ZoomPlugin","ZoomPluginPackage","create","config","reducer","action","removed","remainingDocs"],"mappings":"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"}
package/dist/index.js CHANGED
@@ -20,7 +20,6 @@ const manifest = {
20
20
  requires: ["viewport", "scroll"],
21
21
  optional: ["interaction-manager", "spread"],
22
22
  defaultConfig: {
23
- enabled: true,
24
23
  defaultZoomLevel: ZoomMode.Automatic,
25
24
  minZoom: 0.2,
26
25
  maxZoom: 60,
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sources":["../src/lib/types.ts","../src/lib/manifest.ts","../src/lib/actions.ts","../src/lib/reducer.ts","../src/lib/handlers/marquee-zoom.handler.ts","../src/lib/zoom-plugin.ts","../src/lib/index.ts"],"sourcesContent":["import { BasePluginConfig, EventHook } from '@embedpdf/core';\nimport { Rect } from '@embedpdf/models';\nimport { ViewportMetrics } from '@embedpdf/plugin-viewport';\n\n/* ------------------------------------------------------------------ */\n/* public */\n/* ------------------------------------------------------------------ */\n\nexport enum ZoomMode {\n Automatic = 'automatic',\n FitPage = 'fit-page',\n FitWidth = 'fit-width',\n}\n\nexport type ZoomLevel = ZoomMode | number;\n\nexport interface Point {\n vx: number;\n vy: number;\n}\n\nexport interface ZoomChangeEvent {\n documentId: string;\n /** old and new *actual* scale factors */\n oldZoom: number;\n newZoom: number;\n /** level used to obtain the newZoom (number | mode) */\n level: ZoomLevel;\n /** viewport point kept under the finger / mouse‑wheel focus */\n center: Point;\n /** where the viewport should scroll to after the scale change */\n desiredScrollLeft: number;\n desiredScrollTop: number;\n /** metrics at the moment the zoom was requested */\n viewport: ViewportMetrics;\n}\n\nexport interface StateChangeEvent {\n documentId: string;\n state: ZoomDocumentState;\n}\n\nexport interface MarqueeZoomCallback {\n onPreview?: (rect: Rect | null) => void;\n onCommit?: (rect: Rect) => void;\n onSmallDrag?: () => void;\n}\n\nexport interface RegisterMarqueeOnPageOptions {\n documentId: string;\n pageIndex: number;\n scale: number;\n callback: MarqueeZoomCallback;\n}\n\n// Per-document zoom state\nexport interface ZoomDocumentState {\n zoomLevel: ZoomLevel; // last **requested** level\n currentZoomLevel: number; // actual numeric factor\n isMarqueeZoomActive: boolean; // whether marquee zoom mode is active\n}\n\n// Scoped zoom capability\nexport interface ZoomScope {\n requestZoom(level: ZoomLevel, center?: Point): void;\n requestZoomBy(delta: number, center?: Point): void;\n zoomIn(): void;\n zoomOut(): void;\n zoomToArea(pageIndex: number, rect: Rect): void;\n enableMarqueeZoom(): void;\n disableMarqueeZoom(): void;\n toggleMarqueeZoom(): void;\n isMarqueeZoomActive(): boolean;\n getState(): ZoomDocumentState;\n onZoomChange: EventHook<ZoomChangeEvent>;\n onStateChange: EventHook<ZoomDocumentState>;\n}\n\nexport interface ZoomCapability {\n // Active document operations\n requestZoom(level: ZoomLevel, center?: Point): void;\n requestZoomBy(delta: number, center?: Point): void;\n zoomIn(): void;\n zoomOut(): void;\n zoomToArea(pageIndex: number, rect: Rect): void;\n enableMarqueeZoom(): void;\n disableMarqueeZoom(): void;\n toggleMarqueeZoom(): void;\n isMarqueeZoomActive(): boolean;\n getState(): ZoomDocumentState;\n\n // Document-scoped operations\n forDocument(documentId: string): ZoomScope;\n\n // Global\n registerMarqueeOnPage: (opts: RegisterMarqueeOnPageOptions) => () => void;\n getPresets(): ZoomPreset[];\n\n // Events (include documentId)\n onZoomChange: EventHook<ZoomChangeEvent>;\n onStateChange: EventHook<StateChangeEvent>;\n}\n\n/* ------------------------------------------------------------------ */\n/* config / store */\n/* ------------------------------------------------------------------ */\n\nexport interface ZoomRangeStep {\n min: number;\n max: number;\n step: number;\n}\n\nexport interface ZoomPreset {\n name: string;\n value: ZoomLevel;\n icon?: string;\n}\n\nexport interface ZoomPluginConfig extends BasePluginConfig {\n defaultZoomLevel: ZoomLevel;\n minZoom?: number;\n maxZoom?: number;\n zoomStep?: number;\n zoomRanges?: ZoomRangeStep[];\n presets?: ZoomPreset[];\n}\n\nexport interface ZoomState {\n // Per-document zoom state\n documents: Record<string, ZoomDocumentState>;\n activeDocumentId: string | null;\n}\n\nexport enum VerticalZoomFocus {\n Center,\n Top,\n}\n\nexport interface ZoomRequest {\n level: ZoomLevel;\n delta?: number;\n center?: Point;\n focus?: VerticalZoomFocus;\n align?: 'keep' | 'center';\n}\n","import { PluginManifest } from '@embedpdf/core';\n\nimport { ZoomMode, ZoomPluginConfig } from './types';\n\nexport const ZOOM_PLUGIN_ID = 'zoom';\n\nexport const manifest: PluginManifest<ZoomPluginConfig> = {\n id: ZOOM_PLUGIN_ID,\n name: 'Zoom Plugin',\n version: '1.0.0',\n provides: ['zoom'],\n requires: ['viewport', 'scroll'],\n optional: ['interaction-manager', 'spread'],\n defaultConfig: {\n enabled: true,\n defaultZoomLevel: ZoomMode.Automatic,\n minZoom: 0.2,\n maxZoom: 60,\n zoomStep: 0.1,\n zoomRanges: [\n {\n min: 0.2,\n max: 0.5,\n step: 0.05,\n },\n {\n min: 0.5,\n max: 1.0,\n step: 0.1,\n },\n {\n min: 1.0,\n max: 2.0,\n step: 0.2,\n },\n {\n min: 2.0,\n max: 4.0,\n step: 0.4,\n },\n {\n min: 4.0,\n max: 10.0,\n step: 0.8,\n },\n {\n min: 10.0,\n max: 20.0,\n step: 1.6,\n },\n {\n min: 20.0,\n max: 40.0,\n step: 3.2,\n },\n {\n min: 40.0,\n max: 60.0,\n step: 6.4,\n },\n ],\n presets: [\n {\n name: 'Fit Page',\n value: ZoomMode.FitPage,\n },\n {\n name: 'Fit Width',\n value: ZoomMode.FitWidth,\n },\n {\n name: 'Automatic',\n value: ZoomMode.Automatic,\n },\n {\n name: '25%',\n value: 0.25,\n },\n {\n name: '50%',\n value: 0.5,\n },\n {\n name: '100%',\n value: 1,\n },\n {\n name: '125%',\n value: 1.25,\n },\n {\n name: '150%',\n value: 1.5,\n },\n {\n name: '200%',\n value: 2,\n },\n {\n name: '400%',\n value: 4,\n },\n {\n name: '800%',\n value: 8,\n },\n {\n name: '1600%',\n value: 16,\n },\n ],\n },\n};\n","import { Action } from '@embedpdf/core';\nimport { ZoomLevel, ZoomDocumentState } from './types';\n\n// Document lifecycle\nexport const INIT_ZOOM_STATE = 'ZOOM/INIT_STATE';\nexport const CLEANUP_ZOOM_STATE = 'ZOOM/CLEANUP_STATE';\nexport const SET_ACTIVE_DOCUMENT = 'ZOOM/SET_ACTIVE_DOCUMENT';\n\n// Per-document actions\nexport const SET_ZOOM_LEVEL = 'ZOOM/SET_ZOOM_LEVEL';\nexport const SET_MARQUEE_ZOOM_ACTIVE = 'ZOOM/SET_MARQUEE_ZOOM_ACTIVE';\n\n// Document lifecycle actions\nexport interface InitZoomStateAction extends Action {\n type: typeof INIT_ZOOM_STATE;\n payload: {\n documentId: string;\n state: ZoomDocumentState;\n };\n}\n\nexport interface CleanupZoomStateAction extends Action {\n type: typeof CLEANUP_ZOOM_STATE;\n payload: string; // documentId\n}\n\nexport interface SetActiveDocumentAction extends Action {\n type: typeof SET_ACTIVE_DOCUMENT;\n payload: string | null; // documentId\n}\n\nexport interface SetZoomLevelAction extends Action {\n type: typeof SET_ZOOM_LEVEL;\n payload: {\n documentId: string;\n zoomLevel: ZoomLevel;\n currentZoomLevel: number;\n };\n}\n\nexport interface SetMarqueeZoomActiveAction extends Action {\n type: typeof SET_MARQUEE_ZOOM_ACTIVE;\n payload: {\n documentId: string;\n isActive: boolean;\n };\n}\n\nexport type ZoomAction =\n | InitZoomStateAction\n | CleanupZoomStateAction\n | SetActiveDocumentAction\n | SetZoomLevelAction\n | SetMarqueeZoomActiveAction;\n\n// Action Creators\nexport function initZoomState(documentId: string, state: ZoomDocumentState): InitZoomStateAction {\n return { type: INIT_ZOOM_STATE, payload: { documentId, state } };\n}\n\nexport function cleanupZoomState(documentId: string): CleanupZoomStateAction {\n return { type: CLEANUP_ZOOM_STATE, payload: documentId };\n}\n\nexport function setActiveDocument(documentId: string | null): SetActiveDocumentAction {\n return { type: SET_ACTIVE_DOCUMENT, payload: documentId };\n}\n\nexport function setZoomLevel(\n documentId: string,\n zoomLevel: ZoomLevel,\n currentZoomLevel: number,\n): SetZoomLevelAction {\n return { type: SET_ZOOM_LEVEL, payload: { documentId, zoomLevel, currentZoomLevel } };\n}\n\nexport function setMarqueeZoomActive(\n documentId: string,\n isActive: boolean,\n): SetMarqueeZoomActiveAction {\n return { type: SET_MARQUEE_ZOOM_ACTIVE, payload: { documentId, isActive } };\n}\n","import { Reducer } from '@embedpdf/core';\nimport {\n ZoomAction,\n INIT_ZOOM_STATE,\n CLEANUP_ZOOM_STATE,\n SET_ACTIVE_DOCUMENT,\n SET_ZOOM_LEVEL,\n SET_MARQUEE_ZOOM_ACTIVE,\n} from './actions';\nimport { ZoomState, ZoomDocumentState, ZoomMode } from './types';\n\nexport const initialDocumentState: ZoomDocumentState = {\n zoomLevel: ZoomMode.Automatic,\n currentZoomLevel: 1,\n isMarqueeZoomActive: false,\n};\n\nexport const initialState: ZoomState = {\n documents: {},\n activeDocumentId: null,\n};\n\nexport const zoomReducer: Reducer<ZoomState, ZoomAction> = (state = initialState, action) => {\n switch (action.type) {\n case INIT_ZOOM_STATE: {\n const { documentId, state: docState } = action.payload;\n return {\n ...state,\n documents: {\n ...state.documents,\n [documentId]: docState,\n },\n // Set as active if no active document\n activeDocumentId: state.activeDocumentId ?? documentId,\n };\n }\n\n case CLEANUP_ZOOM_STATE: {\n const documentId = action.payload;\n const { [documentId]: removed, ...remainingDocs } = state.documents;\n return {\n ...state,\n documents: remainingDocs,\n activeDocumentId: state.activeDocumentId === documentId ? null : state.activeDocumentId,\n };\n }\n\n case SET_ACTIVE_DOCUMENT: {\n return {\n ...state,\n activeDocumentId: action.payload,\n };\n }\n\n case SET_ZOOM_LEVEL: {\n const { documentId, zoomLevel, currentZoomLevel } = action.payload;\n const docState = state.documents[documentId];\n if (!docState) return state;\n\n return {\n ...state,\n documents: {\n ...state.documents,\n [documentId]: {\n ...docState,\n zoomLevel,\n currentZoomLevel,\n },\n },\n };\n }\n\n case SET_MARQUEE_ZOOM_ACTIVE: {\n const { documentId, isActive } = action.payload;\n const docState = state.documents[documentId];\n if (!docState) return state;\n\n return {\n ...state,\n documents: {\n ...state.documents,\n [documentId]: {\n ...docState,\n isMarqueeZoomActive: isActive,\n },\n },\n };\n }\n\n default:\n return state;\n }\n};\n","import { Position, Rect, Size } from '@embedpdf/models';\nimport { clamp } from '@embedpdf/core';\nimport {\n EmbedPdfPointerEvent,\n PointerEventHandlersWithLifecycle,\n} from '@embedpdf/plugin-interaction-manager';\n\nexport function createMarqueeHandler(opts: {\n pageSize: Size;\n scale: number;\n minDragPx?: number;\n onPreview?: (rect: Rect | null) => void;\n onCommit?: (rect: Rect) => void;\n onSmallDrag?: () => void;\n}): PointerEventHandlersWithLifecycle<EmbedPdfPointerEvent> {\n const { pageSize, scale, minDragPx = 5, onPreview, onCommit, onSmallDrag } = opts;\n\n let start: Position | null = null;\n let last: Rect | null = null;\n\n return {\n onPointerDown: (pos, evt) => {\n start = pos;\n last = { origin: { x: pos.x, y: pos.y }, size: { width: 0, height: 0 } };\n onPreview?.(last);\n evt.setPointerCapture?.();\n },\n onPointerMove: (pos) => {\n if (!start) return;\n const x = clamp(pos.x, 0, pageSize.width);\n const y = clamp(pos.y, 0, pageSize.height);\n last = {\n origin: { x: Math.min(start.x, x), y: Math.min(start.y, y) },\n size: { width: Math.abs(x - start.x), height: Math.abs(y - start.y) },\n };\n onPreview?.(last);\n },\n onPointerUp: (_pos, evt) => {\n if (last) {\n const dragPx = Math.max(last.size.width, last.size.height) * scale;\n if (dragPx > minDragPx) {\n onCommit?.(last); // Large drag → zoom to area\n } else {\n onSmallDrag?.(); // Small drag → zoom in\n }\n }\n start = null;\n last = null;\n onPreview?.(null);\n evt.releasePointerCapture?.();\n },\n onPointerCancel: (_pos, evt) => {\n start = null;\n last = null;\n onPreview?.(null);\n evt.releasePointerCapture?.();\n },\n };\n}\n","import {\n BasePlugin,\n PluginRegistry,\n createEmitter,\n clamp,\n setScale,\n createBehaviorEmitter,\n Listener,\n} from '@embedpdf/core';\nimport { ScrollPlugin, ScrollCapability } from '@embedpdf/plugin-scroll';\nimport { ViewportPlugin, ViewportCapability, ViewportMetrics } from '@embedpdf/plugin-viewport';\n\nimport {\n initZoomState,\n cleanupZoomState,\n setZoomLevel,\n ZoomAction,\n setMarqueeZoomActive,\n} from './actions';\nimport {\n ZoomPluginConfig,\n ZoomState,\n ZoomMode,\n Point,\n ZoomChangeEvent,\n ZoomCapability,\n ZoomPreset,\n ZoomRangeStep,\n VerticalZoomFocus,\n ZoomRequest,\n RegisterMarqueeOnPageOptions,\n ZoomScope,\n StateChangeEvent,\n ZoomDocumentState,\n} from './types';\nimport {\n InteractionManagerCapability,\n InteractionManagerPlugin,\n} from '@embedpdf/plugin-interaction-manager';\nimport { SpreadCapability, SpreadPlugin } from '@embedpdf/plugin-spread';\nimport { Rect, rotateRect } from '@embedpdf/models';\nimport { createMarqueeHandler } from './handlers';\nimport { initialDocumentState } from './reducer';\n\nexport class ZoomPlugin extends BasePlugin<\n ZoomPluginConfig,\n ZoomCapability,\n ZoomState,\n ZoomAction\n> {\n static readonly id = 'zoom' as const;\n\n private readonly zoom$ = createEmitter<ZoomChangeEvent>();\n private readonly state$ = createBehaviorEmitter<StateChangeEvent>();\n private readonly viewport: ViewportCapability;\n private readonly viewportPlugin: ViewportPlugin;\n private readonly scroll: ScrollCapability;\n private readonly interactionManager: InteractionManagerCapability | null;\n private readonly spread: SpreadCapability | null;\n private readonly presets: ZoomPreset[];\n private readonly zoomRanges: ZoomRangeStep[];\n private readonly defaultZoomLevel: ZoomMode | number;\n\n private readonly minZoom: number;\n private readonly maxZoom: number;\n private readonly zoomStep: number;\n\n constructor(id: string, registry: PluginRegistry, cfg: ZoomPluginConfig) {\n super(id, registry);\n\n this.viewportPlugin = registry.getPlugin<ViewportPlugin>('viewport')!;\n this.viewport = this.viewportPlugin.provides();\n this.scroll = registry.getPlugin<ScrollPlugin>('scroll')!.provides();\n const interactionManager = registry.getPlugin<InteractionManagerPlugin>('interaction-manager');\n this.interactionManager = interactionManager?.provides() ?? null;\n const spread = registry.getPlugin<SpreadPlugin>('spread');\n this.spread = spread?.provides() ?? null;\n\n this.minZoom = cfg.minZoom ?? 0.25;\n this.maxZoom = cfg.maxZoom ?? 10;\n this.zoomStep = cfg.zoomStep ?? 0.1;\n this.defaultZoomLevel = cfg.defaultZoomLevel;\n this.presets = cfg.presets ?? [];\n this.zoomRanges = this.normalizeRanges(cfg.zoomRanges ?? []);\n\n // Keep automatic modes up to date per document\n this.viewport.onViewportResize(\n (event) => this.recalcAuto(event.documentId, VerticalZoomFocus.Top),\n {\n mode: 'debounce',\n wait: 150,\n keyExtractor: (event) => event.documentId,\n },\n );\n\n // Subscribe to spread changes\n this.spread?.onSpreadChange((event) => {\n this.recalcAuto(event.documentId, VerticalZoomFocus.Top);\n });\n\n // Register marquee zoom mode\n this.interactionManager?.registerMode({\n id: 'marqueeZoom',\n scope: 'page',\n exclusive: true,\n cursor: 'zoom-in',\n });\n\n this.interactionManager?.onModeChange((state) => {\n // Track marquee zoom state changes for this document\n const isMarqueeActive = state.activeMode === 'marqueeZoom';\n const docState = this.getDocumentState(state.documentId);\n\n // Only dispatch if state actually changed\n if (docState && docState.isMarqueeZoomActive !== isMarqueeActive) {\n this.dispatch(setMarqueeZoomActive(state.documentId, isMarqueeActive));\n }\n });\n }\n\n // ─────────────────────────────────────────────────────────\n // Document Lifecycle Hooks (from BasePlugin)\n // ─────────────────────────────────────────────────────────\n\n protected override onDocumentLoadingStarted(documentId: string): void {\n this.viewport.gate('zoom', documentId);\n // Initialize zoom state for this document\n const docState: ZoomDocumentState = {\n ...initialDocumentState,\n zoomLevel: this.defaultZoomLevel,\n };\n\n this.dispatch(initZoomState(documentId, docState));\n\n this.logger.debug(\n 'ZoomPlugin',\n 'DocumentOpened',\n `Initialized zoom state for document: ${documentId}`,\n );\n }\n\n protected override onDocumentLoaded(documentId: string): void {\n // Apply initial zoom after document is fully loaded\n this.recalcAuto(documentId, VerticalZoomFocus.Top);\n }\n\n protected override onDocumentClosed(documentId: string): void {\n this.dispatch(cleanupZoomState(documentId));\n\n this.logger.debug(\n 'ZoomPlugin',\n 'DocumentClosed',\n `Cleaned up zoom state for document: ${documentId}`,\n );\n }\n\n protected override onRotationChanged(documentId: string): void {\n // Recalculate auto modes when rotation changes\n this.recalcAuto(documentId, VerticalZoomFocus.Top);\n }\n\n /*\n protected override onPagesChanged(documentId: string): void {\n // Recalculate auto modes when pages change\n this.recalcAuto(documentId, VerticalZoomFocus.Top);\n }*/\n\n // ─────────────────────────────────────────────────────────\n // Capability\n // ─────────────────────────────────────────────────────────\n\n protected buildCapability(): ZoomCapability {\n return {\n // Active document operations\n requestZoom: (level, c) => this.requestZoom(level, c),\n requestZoomBy: (d, c) => this.requestZoomBy(d, c),\n zoomIn: () => this.zoomIn(),\n zoomOut: () => this.zoomOut(),\n zoomToArea: (pageIndex, rect) => this.zoomToArea(pageIndex, rect),\n enableMarqueeZoom: () => this.enableMarqueeZoom(),\n disableMarqueeZoom: () => this.disableMarqueeZoom(),\n toggleMarqueeZoom: () => this.toggleMarqueeZoom(),\n isMarqueeZoomActive: () => this.isMarqueeZoomActive(),\n getState: () => this.getDocumentStateOrThrow(),\n\n // Document-scoped operations\n forDocument: (documentId: string) => this.createZoomScope(documentId),\n\n // Global\n registerMarqueeOnPage: (opts) => this.registerMarqueeOnPage(opts),\n getPresets: () => this.presets,\n\n // Events\n onZoomChange: this.zoom$.on,\n onStateChange: this.state$.on,\n };\n }\n\n // ─────────────────────────────────────────────────────────\n // Document Scoping\n // ─────────────────────────────────────────────────────────\n\n private createZoomScope(documentId: string): ZoomScope {\n return {\n requestZoom: (level, c) => this.requestZoom(level, c, documentId),\n requestZoomBy: (d, c) => this.requestZoomBy(d, c, documentId),\n zoomIn: () => this.zoomIn(documentId),\n zoomOut: () => this.zoomOut(documentId),\n zoomToArea: (pageIndex, rect) => this.zoomToArea(pageIndex, rect, documentId),\n enableMarqueeZoom: () => this.enableMarqueeZoom(documentId),\n disableMarqueeZoom: () => this.disableMarqueeZoom(documentId),\n toggleMarqueeZoom: () => this.toggleMarqueeZoom(documentId),\n isMarqueeZoomActive: () => this.isMarqueeZoomActive(documentId),\n getState: () => this.getDocumentStateOrThrow(documentId),\n onZoomChange: (listener: Listener<ZoomChangeEvent>) =>\n this.zoom$.on((event) => {\n if (event.documentId === documentId) listener(event);\n }),\n onStateChange: (listener: Listener<ZoomDocumentState>) =>\n this.state$.on((event) => {\n if (event.documentId === documentId) listener(event.state);\n }),\n };\n }\n\n // ─────────────────────────────────────────────────────────\n // State Helpers\n // ─────────────────────────────────────────────────────────\n\n private getDocumentState(documentId?: string): ZoomDocumentState | null {\n const id = documentId ?? this.getActiveDocumentId();\n return this.state.documents[id] ?? null;\n }\n\n private getDocumentStateOrThrow(documentId?: string): ZoomDocumentState {\n const state = this.getDocumentState(documentId);\n if (!state) {\n throw new Error(`Zoom state not found for document: ${documentId ?? 'active'}`);\n }\n return state;\n }\n\n // ─────────────────────────────────────────────────────────\n // Core Operations\n // ─────────────────────────────────────────────────────────\n\n private requestZoom(level: ZoomMode | number, center?: Point, documentId?: string): void {\n this.handleRequest({ level, center }, documentId);\n }\n\n private requestZoomBy(delta: number, center?: Point, documentId?: string): void {\n const id = documentId ?? this.getActiveDocumentId();\n const docState = this.getDocumentStateOrThrow(id);\n const cur = docState.currentZoomLevel;\n const target = this.toZoom(cur + delta);\n this.handleRequest({ level: target, center }, id);\n }\n\n private zoomIn(documentId?: string): void {\n const id = documentId ?? this.getActiveDocumentId();\n const docState = this.getDocumentStateOrThrow(id);\n const cur = docState.currentZoomLevel;\n this.handleRequest({ level: cur, delta: this.stepFor(cur) }, id);\n }\n\n private zoomOut(documentId?: string): void {\n const id = documentId ?? this.getActiveDocumentId();\n const docState = this.getDocumentStateOrThrow(id);\n const cur = docState.currentZoomLevel;\n this.handleRequest({ level: cur, delta: -this.stepFor(cur) }, id);\n }\n\n private zoomToArea(pageIndex: number, rect: Rect, documentId?: string): void {\n const id = documentId ?? this.getActiveDocumentId();\n this.handleZoomToArea(id, pageIndex, rect);\n }\n\n private enableMarqueeZoom(documentId?: string): void {\n const id = documentId ?? this.getActiveDocumentId();\n this.interactionManager?.forDocument(id).activate('marqueeZoom');\n }\n\n private disableMarqueeZoom(documentId?: string): void {\n const id = documentId ?? this.getActiveDocumentId();\n this.interactionManager?.forDocument(id).activateDefaultMode();\n }\n\n private toggleMarqueeZoom(documentId?: string): void {\n const id = documentId ?? this.getActiveDocumentId();\n const scope = this.interactionManager?.forDocument(id);\n if (scope?.getActiveMode() === 'marqueeZoom') {\n scope.activateDefaultMode();\n } else {\n scope?.activate('marqueeZoom');\n }\n }\n\n private isMarqueeZoomActive(documentId?: string): boolean {\n const id = documentId ?? this.getActiveDocumentId();\n return this.interactionManager?.forDocument(id).getActiveMode() === 'marqueeZoom';\n }\n\n // ─────────────────────────────────────────────────────────\n // Main Zoom Logic\n // ─────────────────────────────────────────────────────────\n\n private handleRequest(\n { level, delta = 0, center, focus = VerticalZoomFocus.Center, align = 'keep' }: ZoomRequest,\n documentId?: string,\n ) {\n const id = documentId ?? this.getActiveDocumentId();\n const docState = this.getDocumentStateOrThrow(id);\n const coreDoc = this.coreState.core.documents[id];\n if (!coreDoc) return;\n\n const viewport = this.viewport.forDocument(id);\n const metrics = viewport.getMetrics();\n const oldZoom = docState.currentZoomLevel;\n\n if (metrics.clientWidth === 0 || metrics.clientHeight === 0) {\n return;\n }\n\n // Step 1: Resolve target numeric zoom\n const base = typeof level === 'number' ? level : this.computeZoomForMode(id, level, metrics);\n\n if (base === false) return;\n\n const exactZoom = clamp(base + delta, this.minZoom, this.maxZoom);\n const newZoom = Math.floor(exactZoom * 1000) / 1000;\n\n // Step 2: Figure out viewport point to keep under focus\n const focusPoint: Point = center ?? {\n vx: metrics.clientWidth / 2,\n vy: focus === VerticalZoomFocus.Top ? 0 : metrics.clientHeight / 2,\n };\n\n // Step 3: Compute desired scroll offsets\n const { desiredScrollLeft, desiredScrollTop } = this.computeScrollForZoomChange(\n id,\n metrics,\n oldZoom,\n newZoom,\n focusPoint,\n align,\n );\n\n // Step 4: Dispatch and notify\n if (!isNaN(desiredScrollLeft) && !isNaN(desiredScrollTop)) {\n this.viewportPlugin.setViewportScrollMetrics(id, {\n scrollLeft: desiredScrollLeft,\n scrollTop: desiredScrollTop,\n });\n }\n\n this.dispatch(setZoomLevel(id, typeof level === 'number' ? newZoom : level, newZoom));\n this.dispatchCoreAction(setScale(newZoom, id));\n if (this.viewport.isGated(id)) {\n this.viewport.releaseGate('zoom', id);\n }\n\n viewport.scrollTo({\n x: desiredScrollLeft,\n y: desiredScrollTop,\n behavior: 'instant',\n });\n\n const evt: ZoomChangeEvent = {\n documentId: id,\n oldZoom,\n newZoom,\n level,\n center: focusPoint,\n desiredScrollLeft,\n desiredScrollTop,\n viewport: metrics,\n };\n\n this.zoom$.emit(evt);\n }\n\n private computeZoomForMode(\n documentId: string,\n mode: ZoomMode,\n vp: ViewportMetrics,\n ): number | false {\n const coreDoc = this.coreState.core.documents[documentId];\n if (!coreDoc) return false;\n\n const scrollScope = this.scroll.forDocument(documentId);\n const pgGap = scrollScope ? this.scroll.getPageGap() : 0;\n const vpGap = this.viewport.getViewportGap();\n\n const spreads = scrollScope.getSpreadPagesWithRotatedSize();\n if (!spreads.length) return false;\n\n if (vp.clientWidth === 0 || vp.clientHeight === 0) return false;\n\n const availableWidth = vp.clientWidth - 2 * vpGap;\n const availableHeight = vp.clientHeight - 2 * vpGap;\n\n if (availableWidth <= 0 || availableHeight <= 0) return false;\n\n let maxContentW = 0,\n maxContentH = 0;\n\n spreads.forEach((spread) => {\n const contentW = spread.reduce((s, p, i) => s + p.rotatedSize.width + (i ? pgGap : 0), 0);\n const contentH = Math.max(...spread.map((p) => p.rotatedSize.height));\n maxContentW = Math.max(maxContentW, contentW);\n maxContentH = Math.max(maxContentH, contentH);\n });\n\n switch (mode) {\n case ZoomMode.FitWidth:\n return availableWidth / maxContentW;\n case ZoomMode.FitPage:\n return Math.min(availableWidth / maxContentW, availableHeight / maxContentH);\n case ZoomMode.Automatic:\n return Math.min(availableWidth / maxContentW, 1);\n default:\n return 1;\n }\n }\n\n private computeScrollForZoomChange(\n documentId: string,\n vp: ViewportMetrics,\n oldZoom: number,\n newZoom: number,\n focus: Point,\n align: 'keep' | 'center' = 'keep',\n ) {\n const scrollScope = this.scroll.forDocument(documentId);\n const layout = scrollScope.getLayout();\n const vpGap = this.viewport.getViewportGap();\n\n const contentW = layout.totalContentSize.width;\n const contentH = layout.totalContentSize.height;\n\n const availableWidth = vp.clientWidth - 2 * vpGap;\n const availableHeight = vp.clientHeight - 2 * vpGap;\n\n const off = (availableSpace: number, cw: number, zoom: number) =>\n cw * zoom < availableSpace ? (availableSpace - cw * zoom) / 2 : 0;\n\n const offXold = off(availableWidth, contentW, oldZoom);\n const offYold = off(availableHeight, contentH, oldZoom);\n\n const offXnew = off(availableWidth, contentW, newZoom);\n const offYnew = off(availableHeight, contentH, newZoom);\n\n const cx = (vp.scrollLeft + focus.vx - vpGap - offXold) / oldZoom;\n const cy = (vp.scrollTop + focus.vy - vpGap - offYold) / oldZoom;\n\n const baseLeft = cx * newZoom + vpGap + offXnew;\n const baseTop = cy * newZoom + vpGap + offYnew;\n\n const desiredScrollLeft =\n align === 'center' ? baseLeft - vp.clientWidth / 2 : baseLeft - focus.vx;\n const desiredScrollTop =\n align === 'center' ? baseTop - vp.clientHeight / 2 : baseTop - focus.vy;\n\n return {\n desiredScrollLeft: Math.max(0, desiredScrollLeft),\n desiredScrollTop: Math.max(0, desiredScrollTop),\n };\n }\n\n private handleZoomToArea(documentId: string, pageIndex: number, rect: Rect) {\n const coreDoc = this.coreState.core.documents[documentId];\n if (!coreDoc) return;\n\n const rotation = coreDoc.rotation;\n const viewport = this.viewport.forDocument(documentId);\n const vp = viewport.getMetrics();\n const vpGap = this.viewport.getViewportGap();\n const docState = this.getDocumentStateOrThrow(documentId);\n const oldZ = docState.currentZoomLevel;\n\n const availableW = vp.clientWidth - 2 * vpGap;\n const availableH = vp.clientHeight - 2 * vpGap;\n\n const scrollScope = this.scroll.forDocument(documentId);\n const layout = scrollScope.getLayout();\n\n const vItem = layout.virtualItems.find((it) =>\n it.pageLayouts.some((p) => p.pageIndex === pageIndex),\n );\n if (!vItem) return;\n\n const pageRel = vItem.pageLayouts.find((p) => p.pageIndex === pageIndex)!;\n\n const rotatedRect = rotateRect(\n { width: pageRel.width, height: pageRel.height },\n rect,\n rotation,\n );\n\n const targetZoom = this.toZoom(\n Math.min(availableW / rotatedRect.size.width, availableH / rotatedRect.size.height),\n );\n\n const pageAbsX = vItem.x + pageRel.x;\n const pageAbsY = vItem.y + pageRel.y;\n\n const cxContent = pageAbsX + rotatedRect.origin.x + rotatedRect.size.width / 2;\n const cyContent = pageAbsY + rotatedRect.origin.y + rotatedRect.size.height / 2;\n\n const off = (avail: number, cw: number, z: number) =>\n cw * z < avail ? (avail - cw * z) / 2 : 0;\n\n const offXold = off(availableW, layout.totalContentSize.width, oldZ);\n const offYold = off(availableH, layout.totalContentSize.height, oldZ);\n\n const centerVX = vpGap + offXold + cxContent * oldZ - vp.scrollLeft;\n const centerVY = vpGap + offYold + cyContent * oldZ - vp.scrollTop;\n\n this.handleRequest(\n {\n level: targetZoom,\n center: { vx: centerVX, vy: centerVY },\n align: 'center',\n },\n documentId,\n );\n }\n\n private recalcAuto(documentId: string, focus?: VerticalZoomFocus) {\n const docState = this.getDocumentState(documentId);\n if (!docState) return;\n\n if (\n docState.zoomLevel === ZoomMode.Automatic ||\n docState.zoomLevel === ZoomMode.FitPage ||\n docState.zoomLevel === ZoomMode.FitWidth\n ) {\n this.handleRequest({ level: docState.zoomLevel, focus }, documentId);\n }\n }\n\n // ─────────────────────────────────────────────────────────\n // Helpers\n // ─────────────────────────────────────────────────────────\n\n private normalizeRanges(ranges: ZoomRangeStep[]): ZoomRangeStep[] {\n return [...ranges].filter((r) => r.step > 0 && r.max > r.min).sort((a, b) => a.min - b.min);\n }\n\n private stepFor(zoom: number): number {\n const r = this.zoomRanges.find((r) => zoom >= r.min && zoom < r.max);\n return r ? r.step : this.zoomStep;\n }\n\n private toZoom(v: number) {\n return parseFloat(clamp(v, this.minZoom, this.maxZoom).toFixed(2));\n }\n\n // ─────────────────────────────────────────────────────────\n // Marquee Zoom\n // ─────────────────────────────────────────────────────────\n\n public registerMarqueeOnPage(opts: RegisterMarqueeOnPageOptions) {\n if (!this.interactionManager) {\n this.logger.warn(\n 'ZoomPlugin',\n 'MissingDependency',\n 'Interaction manager plugin not loaded, marquee zoom disabled',\n );\n return () => {};\n }\n\n const coreDoc = this.coreState.core.documents[opts.documentId];\n if (!coreDoc || !coreDoc.document) {\n this.logger.warn('ZoomPlugin', 'DocumentNotFound', 'Document not found');\n return () => {};\n }\n\n const page = coreDoc.document.pages[opts.pageIndex];\n if (!page) {\n this.logger.warn('ZoomPlugin', 'PageNotFound', `Page ${opts.pageIndex} not found`);\n return () => {};\n }\n\n const handlers = createMarqueeHandler({\n pageSize: page.size,\n scale: opts.scale,\n onPreview: opts.callback.onPreview,\n onCommit: (rect) => {\n this.zoomToArea(opts.pageIndex, rect, opts.documentId);\n opts.callback.onCommit?.(rect);\n },\n onSmallDrag: () => {\n this.zoomIn(opts.documentId);\n opts.callback.onSmallDrag?.();\n },\n });\n\n const off = this.interactionManager.registerHandlers({\n documentId: opts.documentId,\n modeId: 'marqueeZoom',\n handlers,\n pageIndex: opts.pageIndex,\n });\n\n return off;\n }\n\n // ─────────────────────────────────────────────────────────\n // Store Update Handlers\n // ─────────────────────────────────────────────────────────\n\n override onStoreUpdated(prevState: ZoomState, newState: ZoomState): void {\n // Emit state changes for each changed document\n for (const documentId in newState.documents) {\n const prevDoc = prevState.documents[documentId];\n const newDoc = newState.documents[documentId];\n\n if (\n prevDoc &&\n newDoc &&\n (prevDoc.currentZoomLevel !== newDoc.currentZoomLevel ||\n prevDoc.zoomLevel !== newDoc.zoomLevel ||\n prevDoc.isMarqueeZoomActive !== newDoc.isMarqueeZoomActive)\n ) {\n this.state$.emit({\n documentId,\n state: newDoc,\n });\n }\n }\n }\n\n // ─────────────────────────────────────────────────────────\n // Lifecycle\n // ─────────────────────────────────────────────────────────\n\n async initialize(): Promise<void> {\n this.logger.info('ZoomPlugin', 'Initialize', 'Zoom plugin initialized');\n }\n\n async destroy() {\n this.zoom$.clear();\n this.state$.clear();\n super.destroy();\n }\n}\n","import { PluginPackage } from '@embedpdf/core';\n\nimport { ZoomAction } from './actions';\nimport { manifest, ZOOM_PLUGIN_ID } from './manifest';\nimport { zoomReducer, initialState, initialDocumentState } from './reducer';\nimport { ZoomPluginConfig, ZoomState } from './types';\nimport { ZoomPlugin } from './zoom-plugin';\n\nexport const ZoomPluginPackage: PluginPackage<ZoomPlugin, ZoomPluginConfig, ZoomState, ZoomAction> =\n {\n manifest,\n create: (registry, config) => new ZoomPlugin(ZOOM_PLUGIN_ID, registry, config),\n reducer: zoomReducer,\n initialState,\n };\n\nexport * from './zoom-plugin';\nexport * from './types';\nexport * from './manifest';\nexport { initialState, initialDocumentState };\n"],"names":["ZoomMode","VerticalZoomFocus","r"],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sources":["../src/lib/types.ts","../src/lib/manifest.ts","../src/lib/actions.ts","../src/lib/reducer.ts","../src/lib/handlers/marquee-zoom.handler.ts","../src/lib/zoom-plugin.ts","../src/lib/index.ts"],"sourcesContent":["import { BasePluginConfig, EventHook } from '@embedpdf/core';\nimport { Rect } from '@embedpdf/models';\nimport { ViewportMetrics } from '@embedpdf/plugin-viewport';\n\n/* ------------------------------------------------------------------ */\n/* public */\n/* ------------------------------------------------------------------ */\n\nexport enum ZoomMode {\n Automatic = 'automatic',\n FitPage = 'fit-page',\n FitWidth = 'fit-width',\n}\n\nexport type ZoomLevel = ZoomMode | number;\n\nexport interface Point {\n vx: number;\n vy: number;\n}\n\nexport interface ZoomChangeEvent {\n documentId: string;\n /** old and new *actual* scale factors */\n oldZoom: number;\n newZoom: number;\n /** level used to obtain the newZoom (number | mode) */\n level: ZoomLevel;\n /** viewport point kept under the finger / mouse‑wheel focus */\n center: Point;\n /** where the viewport should scroll to after the scale change */\n desiredScrollLeft: number;\n desiredScrollTop: number;\n /** metrics at the moment the zoom was requested */\n viewport: ViewportMetrics;\n}\n\nexport interface StateChangeEvent {\n documentId: string;\n state: ZoomDocumentState;\n}\n\nexport interface MarqueeZoomCallback {\n onPreview?: (rect: Rect | null) => void;\n onCommit?: (rect: Rect) => void;\n onSmallDrag?: () => void;\n}\n\nexport interface RegisterMarqueeOnPageOptions {\n documentId: string;\n pageIndex: number;\n scale: number;\n callback: MarqueeZoomCallback;\n}\n\n// Per-document zoom state\nexport interface ZoomDocumentState {\n zoomLevel: ZoomLevel; // last **requested** level\n currentZoomLevel: number; // actual numeric factor\n isMarqueeZoomActive: boolean; // whether marquee zoom mode is active\n}\n\n// Scoped zoom capability\nexport interface ZoomScope {\n requestZoom(level: ZoomLevel, center?: Point): void;\n requestZoomBy(delta: number, center?: Point): void;\n zoomIn(): void;\n zoomOut(): void;\n zoomToArea(pageIndex: number, rect: Rect): void;\n enableMarqueeZoom(): void;\n disableMarqueeZoom(): void;\n toggleMarqueeZoom(): void;\n isMarqueeZoomActive(): boolean;\n getState(): ZoomDocumentState;\n onZoomChange: EventHook<ZoomChangeEvent>;\n onStateChange: EventHook<ZoomDocumentState>;\n}\n\nexport interface ZoomCapability {\n // Active document operations\n requestZoom(level: ZoomLevel, center?: Point): void;\n requestZoomBy(delta: number, center?: Point): void;\n zoomIn(): void;\n zoomOut(): void;\n zoomToArea(pageIndex: number, rect: Rect): void;\n enableMarqueeZoom(): void;\n disableMarqueeZoom(): void;\n toggleMarqueeZoom(): void;\n isMarqueeZoomActive(): boolean;\n getState(): ZoomDocumentState;\n\n // Document-scoped operations\n forDocument(documentId: string): ZoomScope;\n\n // Global\n registerMarqueeOnPage: (opts: RegisterMarqueeOnPageOptions) => () => void;\n getPresets(): ZoomPreset[];\n\n // Events (include documentId)\n onZoomChange: EventHook<ZoomChangeEvent>;\n onStateChange: EventHook<StateChangeEvent>;\n}\n\n/* ------------------------------------------------------------------ */\n/* config / store */\n/* ------------------------------------------------------------------ */\n\nexport interface ZoomRangeStep {\n min: number;\n max: number;\n step: number;\n}\n\nexport interface ZoomPreset {\n name: string;\n value: ZoomLevel;\n icon?: string;\n}\n\nexport interface ZoomPluginConfig extends BasePluginConfig {\n defaultZoomLevel: ZoomLevel;\n minZoom?: number;\n maxZoom?: number;\n zoomStep?: number;\n zoomRanges?: ZoomRangeStep[];\n presets?: ZoomPreset[];\n}\n\nexport interface ZoomState {\n // Per-document zoom state\n documents: Record<string, ZoomDocumentState>;\n activeDocumentId: string | null;\n}\n\nexport enum VerticalZoomFocus {\n Center,\n Top,\n}\n\nexport interface ZoomRequest {\n level: ZoomLevel;\n delta?: number;\n center?: Point;\n focus?: VerticalZoomFocus;\n align?: 'keep' | 'center';\n}\n","import { PluginManifest } from '@embedpdf/core';\n\nimport { ZoomMode, ZoomPluginConfig } from './types';\n\nexport const ZOOM_PLUGIN_ID = 'zoom';\n\nexport const manifest: PluginManifest<ZoomPluginConfig> = {\n id: ZOOM_PLUGIN_ID,\n name: 'Zoom Plugin',\n version: '1.0.0',\n provides: ['zoom'],\n requires: ['viewport', 'scroll'],\n optional: ['interaction-manager', 'spread'],\n defaultConfig: {\n defaultZoomLevel: ZoomMode.Automatic,\n minZoom: 0.2,\n maxZoom: 60,\n zoomStep: 0.1,\n zoomRanges: [\n {\n min: 0.2,\n max: 0.5,\n step: 0.05,\n },\n {\n min: 0.5,\n max: 1.0,\n step: 0.1,\n },\n {\n min: 1.0,\n max: 2.0,\n step: 0.2,\n },\n {\n min: 2.0,\n max: 4.0,\n step: 0.4,\n },\n {\n min: 4.0,\n max: 10.0,\n step: 0.8,\n },\n {\n min: 10.0,\n max: 20.0,\n step: 1.6,\n },\n {\n min: 20.0,\n max: 40.0,\n step: 3.2,\n },\n {\n min: 40.0,\n max: 60.0,\n step: 6.4,\n },\n ],\n presets: [\n {\n name: 'Fit Page',\n value: ZoomMode.FitPage,\n },\n {\n name: 'Fit Width',\n value: ZoomMode.FitWidth,\n },\n {\n name: 'Automatic',\n value: ZoomMode.Automatic,\n },\n {\n name: '25%',\n value: 0.25,\n },\n {\n name: '50%',\n value: 0.5,\n },\n {\n name: '100%',\n value: 1,\n },\n {\n name: '125%',\n value: 1.25,\n },\n {\n name: '150%',\n value: 1.5,\n },\n {\n name: '200%',\n value: 2,\n },\n {\n name: '400%',\n value: 4,\n },\n {\n name: '800%',\n value: 8,\n },\n {\n name: '1600%',\n value: 16,\n },\n ],\n },\n};\n","import { Action } from '@embedpdf/core';\nimport { ZoomLevel, ZoomDocumentState } from './types';\n\n// Document lifecycle\nexport const INIT_ZOOM_STATE = 'ZOOM/INIT_STATE';\nexport const CLEANUP_ZOOM_STATE = 'ZOOM/CLEANUP_STATE';\nexport const SET_ACTIVE_DOCUMENT = 'ZOOM/SET_ACTIVE_DOCUMENT';\n\n// Per-document actions\nexport const SET_ZOOM_LEVEL = 'ZOOM/SET_ZOOM_LEVEL';\nexport const SET_MARQUEE_ZOOM_ACTIVE = 'ZOOM/SET_MARQUEE_ZOOM_ACTIVE';\n\n// Document lifecycle actions\nexport interface InitZoomStateAction extends Action {\n type: typeof INIT_ZOOM_STATE;\n payload: {\n documentId: string;\n state: ZoomDocumentState;\n };\n}\n\nexport interface CleanupZoomStateAction extends Action {\n type: typeof CLEANUP_ZOOM_STATE;\n payload: string; // documentId\n}\n\nexport interface SetActiveDocumentAction extends Action {\n type: typeof SET_ACTIVE_DOCUMENT;\n payload: string | null; // documentId\n}\n\nexport interface SetZoomLevelAction extends Action {\n type: typeof SET_ZOOM_LEVEL;\n payload: {\n documentId: string;\n zoomLevel: ZoomLevel;\n currentZoomLevel: number;\n };\n}\n\nexport interface SetMarqueeZoomActiveAction extends Action {\n type: typeof SET_MARQUEE_ZOOM_ACTIVE;\n payload: {\n documentId: string;\n isActive: boolean;\n };\n}\n\nexport type ZoomAction =\n | InitZoomStateAction\n | CleanupZoomStateAction\n | SetActiveDocumentAction\n | SetZoomLevelAction\n | SetMarqueeZoomActiveAction;\n\n// Action Creators\nexport function initZoomState(documentId: string, state: ZoomDocumentState): InitZoomStateAction {\n return { type: INIT_ZOOM_STATE, payload: { documentId, state } };\n}\n\nexport function cleanupZoomState(documentId: string): CleanupZoomStateAction {\n return { type: CLEANUP_ZOOM_STATE, payload: documentId };\n}\n\nexport function setActiveDocument(documentId: string | null): SetActiveDocumentAction {\n return { type: SET_ACTIVE_DOCUMENT, payload: documentId };\n}\n\nexport function setZoomLevel(\n documentId: string,\n zoomLevel: ZoomLevel,\n currentZoomLevel: number,\n): SetZoomLevelAction {\n return { type: SET_ZOOM_LEVEL, payload: { documentId, zoomLevel, currentZoomLevel } };\n}\n\nexport function setMarqueeZoomActive(\n documentId: string,\n isActive: boolean,\n): SetMarqueeZoomActiveAction {\n return { type: SET_MARQUEE_ZOOM_ACTIVE, payload: { documentId, isActive } };\n}\n","import { Reducer } from '@embedpdf/core';\nimport {\n ZoomAction,\n INIT_ZOOM_STATE,\n CLEANUP_ZOOM_STATE,\n SET_ACTIVE_DOCUMENT,\n SET_ZOOM_LEVEL,\n SET_MARQUEE_ZOOM_ACTIVE,\n} from './actions';\nimport { ZoomState, ZoomDocumentState, ZoomMode } from './types';\n\nexport const initialDocumentState: ZoomDocumentState = {\n zoomLevel: ZoomMode.Automatic,\n currentZoomLevel: 1,\n isMarqueeZoomActive: false,\n};\n\nexport const initialState: ZoomState = {\n documents: {},\n activeDocumentId: null,\n};\n\nexport const zoomReducer: Reducer<ZoomState, ZoomAction> = (state = initialState, action) => {\n switch (action.type) {\n case INIT_ZOOM_STATE: {\n const { documentId, state: docState } = action.payload;\n return {\n ...state,\n documents: {\n ...state.documents,\n [documentId]: docState,\n },\n // Set as active if no active document\n activeDocumentId: state.activeDocumentId ?? documentId,\n };\n }\n\n case CLEANUP_ZOOM_STATE: {\n const documentId = action.payload;\n const { [documentId]: removed, ...remainingDocs } = state.documents;\n return {\n ...state,\n documents: remainingDocs,\n activeDocumentId: state.activeDocumentId === documentId ? null : state.activeDocumentId,\n };\n }\n\n case SET_ACTIVE_DOCUMENT: {\n return {\n ...state,\n activeDocumentId: action.payload,\n };\n }\n\n case SET_ZOOM_LEVEL: {\n const { documentId, zoomLevel, currentZoomLevel } = action.payload;\n const docState = state.documents[documentId];\n if (!docState) return state;\n\n return {\n ...state,\n documents: {\n ...state.documents,\n [documentId]: {\n ...docState,\n zoomLevel,\n currentZoomLevel,\n },\n },\n };\n }\n\n case SET_MARQUEE_ZOOM_ACTIVE: {\n const { documentId, isActive } = action.payload;\n const docState = state.documents[documentId];\n if (!docState) return state;\n\n return {\n ...state,\n documents: {\n ...state.documents,\n [documentId]: {\n ...docState,\n isMarqueeZoomActive: isActive,\n },\n },\n };\n }\n\n default:\n return state;\n }\n};\n","import { Position, Rect, Size } from '@embedpdf/models';\nimport { clamp } from '@embedpdf/core';\nimport {\n EmbedPdfPointerEvent,\n PointerEventHandlersWithLifecycle,\n} from '@embedpdf/plugin-interaction-manager';\n\nexport function createMarqueeHandler(opts: {\n pageSize: Size;\n scale: number;\n minDragPx?: number;\n onPreview?: (rect: Rect | null) => void;\n onCommit?: (rect: Rect) => void;\n onSmallDrag?: () => void;\n}): PointerEventHandlersWithLifecycle<EmbedPdfPointerEvent> {\n const { pageSize, scale, minDragPx = 5, onPreview, onCommit, onSmallDrag } = opts;\n\n let start: Position | null = null;\n let last: Rect | null = null;\n\n return {\n onPointerDown: (pos, evt) => {\n start = pos;\n last = { origin: { x: pos.x, y: pos.y }, size: { width: 0, height: 0 } };\n onPreview?.(last);\n evt.setPointerCapture?.();\n },\n onPointerMove: (pos) => {\n if (!start) return;\n const x = clamp(pos.x, 0, pageSize.width);\n const y = clamp(pos.y, 0, pageSize.height);\n last = {\n origin: { x: Math.min(start.x, x), y: Math.min(start.y, y) },\n size: { width: Math.abs(x - start.x), height: Math.abs(y - start.y) },\n };\n onPreview?.(last);\n },\n onPointerUp: (_pos, evt) => {\n if (last) {\n const dragPx = Math.max(last.size.width, last.size.height) * scale;\n if (dragPx > minDragPx) {\n onCommit?.(last); // Large drag → zoom to area\n } else {\n onSmallDrag?.(); // Small drag → zoom in\n }\n }\n start = null;\n last = null;\n onPreview?.(null);\n evt.releasePointerCapture?.();\n },\n onPointerCancel: (_pos, evt) => {\n start = null;\n last = null;\n onPreview?.(null);\n evt.releasePointerCapture?.();\n },\n };\n}\n","import {\n BasePlugin,\n PluginRegistry,\n createEmitter,\n clamp,\n setScale,\n createBehaviorEmitter,\n Listener,\n} from '@embedpdf/core';\nimport { ScrollPlugin, ScrollCapability } from '@embedpdf/plugin-scroll';\nimport { ViewportPlugin, ViewportCapability, ViewportMetrics } from '@embedpdf/plugin-viewport';\n\nimport {\n initZoomState,\n cleanupZoomState,\n setZoomLevel,\n ZoomAction,\n setMarqueeZoomActive,\n} from './actions';\nimport {\n ZoomPluginConfig,\n ZoomState,\n ZoomMode,\n Point,\n ZoomChangeEvent,\n ZoomCapability,\n ZoomPreset,\n ZoomRangeStep,\n VerticalZoomFocus,\n ZoomRequest,\n RegisterMarqueeOnPageOptions,\n ZoomScope,\n StateChangeEvent,\n ZoomDocumentState,\n} from './types';\nimport {\n InteractionManagerCapability,\n InteractionManagerPlugin,\n} from '@embedpdf/plugin-interaction-manager';\nimport { SpreadCapability, SpreadPlugin } from '@embedpdf/plugin-spread';\nimport { Rect, rotateRect } from '@embedpdf/models';\nimport { createMarqueeHandler } from './handlers';\nimport { initialDocumentState } from './reducer';\n\nexport class ZoomPlugin extends BasePlugin<\n ZoomPluginConfig,\n ZoomCapability,\n ZoomState,\n ZoomAction\n> {\n static readonly id = 'zoom' as const;\n\n private readonly zoom$ = createEmitter<ZoomChangeEvent>();\n private readonly state$ = createBehaviorEmitter<StateChangeEvent>();\n private readonly viewport: ViewportCapability;\n private readonly viewportPlugin: ViewportPlugin;\n private readonly scroll: ScrollCapability;\n private readonly interactionManager: InteractionManagerCapability | null;\n private readonly spread: SpreadCapability | null;\n private readonly presets: ZoomPreset[];\n private readonly zoomRanges: ZoomRangeStep[];\n private readonly defaultZoomLevel: ZoomMode | number;\n\n private readonly minZoom: number;\n private readonly maxZoom: number;\n private readonly zoomStep: number;\n\n constructor(id: string, registry: PluginRegistry, cfg: ZoomPluginConfig) {\n super(id, registry);\n\n this.viewportPlugin = registry.getPlugin<ViewportPlugin>('viewport')!;\n this.viewport = this.viewportPlugin.provides();\n this.scroll = registry.getPlugin<ScrollPlugin>('scroll')!.provides();\n const interactionManager = registry.getPlugin<InteractionManagerPlugin>('interaction-manager');\n this.interactionManager = interactionManager?.provides() ?? null;\n const spread = registry.getPlugin<SpreadPlugin>('spread');\n this.spread = spread?.provides() ?? null;\n\n this.minZoom = cfg.minZoom ?? 0.25;\n this.maxZoom = cfg.maxZoom ?? 10;\n this.zoomStep = cfg.zoomStep ?? 0.1;\n this.defaultZoomLevel = cfg.defaultZoomLevel;\n this.presets = cfg.presets ?? [];\n this.zoomRanges = this.normalizeRanges(cfg.zoomRanges ?? []);\n\n // Keep automatic modes up to date per document\n this.viewport.onViewportResize(\n (event) => this.recalcAuto(event.documentId, VerticalZoomFocus.Top),\n {\n mode: 'debounce',\n wait: 150,\n keyExtractor: (event) => event.documentId,\n },\n );\n\n // Subscribe to spread changes\n this.spread?.onSpreadChange((event) => {\n this.recalcAuto(event.documentId, VerticalZoomFocus.Top);\n });\n\n // Register marquee zoom mode\n this.interactionManager?.registerMode({\n id: 'marqueeZoom',\n scope: 'page',\n exclusive: true,\n cursor: 'zoom-in',\n });\n\n this.interactionManager?.onModeChange((state) => {\n // Track marquee zoom state changes for this document\n const isMarqueeActive = state.activeMode === 'marqueeZoom';\n const docState = this.getDocumentState(state.documentId);\n\n // Only dispatch if state actually changed\n if (docState && docState.isMarqueeZoomActive !== isMarqueeActive) {\n this.dispatch(setMarqueeZoomActive(state.documentId, isMarqueeActive));\n }\n });\n }\n\n // ─────────────────────────────────────────────────────────\n // Document Lifecycle Hooks (from BasePlugin)\n // ─────────────────────────────────────────────────────────\n\n protected override onDocumentLoadingStarted(documentId: string): void {\n this.viewport.gate('zoom', documentId);\n // Initialize zoom state for this document\n const docState: ZoomDocumentState = {\n ...initialDocumentState,\n zoomLevel: this.defaultZoomLevel,\n };\n\n this.dispatch(initZoomState(documentId, docState));\n\n this.logger.debug(\n 'ZoomPlugin',\n 'DocumentOpened',\n `Initialized zoom state for document: ${documentId}`,\n );\n }\n\n protected override onDocumentLoaded(documentId: string): void {\n // Apply initial zoom after document is fully loaded\n this.recalcAuto(documentId, VerticalZoomFocus.Top);\n }\n\n protected override onDocumentClosed(documentId: string): void {\n this.dispatch(cleanupZoomState(documentId));\n\n this.logger.debug(\n 'ZoomPlugin',\n 'DocumentClosed',\n `Cleaned up zoom state for document: ${documentId}`,\n );\n }\n\n protected override onRotationChanged(documentId: string): void {\n // Recalculate auto modes when rotation changes\n this.recalcAuto(documentId, VerticalZoomFocus.Top);\n }\n\n /*\n protected override onPagesChanged(documentId: string): void {\n // Recalculate auto modes when pages change\n this.recalcAuto(documentId, VerticalZoomFocus.Top);\n }*/\n\n // ─────────────────────────────────────────────────────────\n // Capability\n // ─────────────────────────────────────────────────────────\n\n protected buildCapability(): ZoomCapability {\n return {\n // Active document operations\n requestZoom: (level, c) => this.requestZoom(level, c),\n requestZoomBy: (d, c) => this.requestZoomBy(d, c),\n zoomIn: () => this.zoomIn(),\n zoomOut: () => this.zoomOut(),\n zoomToArea: (pageIndex, rect) => this.zoomToArea(pageIndex, rect),\n enableMarqueeZoom: () => this.enableMarqueeZoom(),\n disableMarqueeZoom: () => this.disableMarqueeZoom(),\n toggleMarqueeZoom: () => this.toggleMarqueeZoom(),\n isMarqueeZoomActive: () => this.isMarqueeZoomActive(),\n getState: () => this.getDocumentStateOrThrow(),\n\n // Document-scoped operations\n forDocument: (documentId: string) => this.createZoomScope(documentId),\n\n // Global\n registerMarqueeOnPage: (opts) => this.registerMarqueeOnPage(opts),\n getPresets: () => this.presets,\n\n // Events\n onZoomChange: this.zoom$.on,\n onStateChange: this.state$.on,\n };\n }\n\n // ─────────────────────────────────────────────────────────\n // Document Scoping\n // ─────────────────────────────────────────────────────────\n\n private createZoomScope(documentId: string): ZoomScope {\n return {\n requestZoom: (level, c) => this.requestZoom(level, c, documentId),\n requestZoomBy: (d, c) => this.requestZoomBy(d, c, documentId),\n zoomIn: () => this.zoomIn(documentId),\n zoomOut: () => this.zoomOut(documentId),\n zoomToArea: (pageIndex, rect) => this.zoomToArea(pageIndex, rect, documentId),\n enableMarqueeZoom: () => this.enableMarqueeZoom(documentId),\n disableMarqueeZoom: () => this.disableMarqueeZoom(documentId),\n toggleMarqueeZoom: () => this.toggleMarqueeZoom(documentId),\n isMarqueeZoomActive: () => this.isMarqueeZoomActive(documentId),\n getState: () => this.getDocumentStateOrThrow(documentId),\n onZoomChange: (listener: Listener<ZoomChangeEvent>) =>\n this.zoom$.on((event) => {\n if (event.documentId === documentId) listener(event);\n }),\n onStateChange: (listener: Listener<ZoomDocumentState>) =>\n this.state$.on((event) => {\n if (event.documentId === documentId) listener(event.state);\n }),\n };\n }\n\n // ─────────────────────────────────────────────────────────\n // State Helpers\n // ─────────────────────────────────────────────────────────\n\n private getDocumentState(documentId?: string): ZoomDocumentState | null {\n const id = documentId ?? this.getActiveDocumentId();\n return this.state.documents[id] ?? null;\n }\n\n private getDocumentStateOrThrow(documentId?: string): ZoomDocumentState {\n const state = this.getDocumentState(documentId);\n if (!state) {\n throw new Error(`Zoom state not found for document: ${documentId ?? 'active'}`);\n }\n return state;\n }\n\n // ─────────────────────────────────────────────────────────\n // Core Operations\n // ─────────────────────────────────────────────────────────\n\n private requestZoom(level: ZoomMode | number, center?: Point, documentId?: string): void {\n this.handleRequest({ level, center }, documentId);\n }\n\n private requestZoomBy(delta: number, center?: Point, documentId?: string): void {\n const id = documentId ?? this.getActiveDocumentId();\n const docState = this.getDocumentStateOrThrow(id);\n const cur = docState.currentZoomLevel;\n const target = this.toZoom(cur + delta);\n this.handleRequest({ level: target, center }, id);\n }\n\n private zoomIn(documentId?: string): void {\n const id = documentId ?? this.getActiveDocumentId();\n const docState = this.getDocumentStateOrThrow(id);\n const cur = docState.currentZoomLevel;\n this.handleRequest({ level: cur, delta: this.stepFor(cur) }, id);\n }\n\n private zoomOut(documentId?: string): void {\n const id = documentId ?? this.getActiveDocumentId();\n const docState = this.getDocumentStateOrThrow(id);\n const cur = docState.currentZoomLevel;\n this.handleRequest({ level: cur, delta: -this.stepFor(cur) }, id);\n }\n\n private zoomToArea(pageIndex: number, rect: Rect, documentId?: string): void {\n const id = documentId ?? this.getActiveDocumentId();\n this.handleZoomToArea(id, pageIndex, rect);\n }\n\n private enableMarqueeZoom(documentId?: string): void {\n const id = documentId ?? this.getActiveDocumentId();\n this.interactionManager?.forDocument(id).activate('marqueeZoom');\n }\n\n private disableMarqueeZoom(documentId?: string): void {\n const id = documentId ?? this.getActiveDocumentId();\n this.interactionManager?.forDocument(id).activateDefaultMode();\n }\n\n private toggleMarqueeZoom(documentId?: string): void {\n const id = documentId ?? this.getActiveDocumentId();\n const scope = this.interactionManager?.forDocument(id);\n if (scope?.getActiveMode() === 'marqueeZoom') {\n scope.activateDefaultMode();\n } else {\n scope?.activate('marqueeZoom');\n }\n }\n\n private isMarqueeZoomActive(documentId?: string): boolean {\n const id = documentId ?? this.getActiveDocumentId();\n return this.interactionManager?.forDocument(id).getActiveMode() === 'marqueeZoom';\n }\n\n // ─────────────────────────────────────────────────────────\n // Main Zoom Logic\n // ─────────────────────────────────────────────────────────\n\n private handleRequest(\n { level, delta = 0, center, focus = VerticalZoomFocus.Center, align = 'keep' }: ZoomRequest,\n documentId?: string,\n ) {\n const id = documentId ?? this.getActiveDocumentId();\n const docState = this.getDocumentStateOrThrow(id);\n const coreDoc = this.coreState.core.documents[id];\n if (!coreDoc) return;\n\n const viewport = this.viewport.forDocument(id);\n const metrics = viewport.getMetrics();\n const oldZoom = docState.currentZoomLevel;\n\n if (metrics.clientWidth === 0 || metrics.clientHeight === 0) {\n return;\n }\n\n // Step 1: Resolve target numeric zoom\n const base = typeof level === 'number' ? level : this.computeZoomForMode(id, level, metrics);\n\n if (base === false) return;\n\n const exactZoom = clamp(base + delta, this.minZoom, this.maxZoom);\n const newZoom = Math.floor(exactZoom * 1000) / 1000;\n\n // Step 2: Figure out viewport point to keep under focus\n const focusPoint: Point = center ?? {\n vx: metrics.clientWidth / 2,\n vy: focus === VerticalZoomFocus.Top ? 0 : metrics.clientHeight / 2,\n };\n\n // Step 3: Compute desired scroll offsets\n const { desiredScrollLeft, desiredScrollTop } = this.computeScrollForZoomChange(\n id,\n metrics,\n oldZoom,\n newZoom,\n focusPoint,\n align,\n );\n\n // Step 4: Dispatch and notify\n if (!isNaN(desiredScrollLeft) && !isNaN(desiredScrollTop)) {\n this.viewportPlugin.setViewportScrollMetrics(id, {\n scrollLeft: desiredScrollLeft,\n scrollTop: desiredScrollTop,\n });\n }\n\n this.dispatch(setZoomLevel(id, typeof level === 'number' ? newZoom : level, newZoom));\n this.dispatchCoreAction(setScale(newZoom, id));\n if (this.viewport.isGated(id)) {\n this.viewport.releaseGate('zoom', id);\n }\n\n viewport.scrollTo({\n x: desiredScrollLeft,\n y: desiredScrollTop,\n behavior: 'instant',\n });\n\n const evt: ZoomChangeEvent = {\n documentId: id,\n oldZoom,\n newZoom,\n level,\n center: focusPoint,\n desiredScrollLeft,\n desiredScrollTop,\n viewport: metrics,\n };\n\n this.zoom$.emit(evt);\n }\n\n private computeZoomForMode(\n documentId: string,\n mode: ZoomMode,\n vp: ViewportMetrics,\n ): number | false {\n const coreDoc = this.coreState.core.documents[documentId];\n if (!coreDoc) return false;\n\n const scrollScope = this.scroll.forDocument(documentId);\n const pgGap = scrollScope ? this.scroll.getPageGap() : 0;\n const vpGap = this.viewport.getViewportGap();\n\n const spreads = scrollScope.getSpreadPagesWithRotatedSize();\n if (!spreads.length) return false;\n\n if (vp.clientWidth === 0 || vp.clientHeight === 0) return false;\n\n const availableWidth = vp.clientWidth - 2 * vpGap;\n const availableHeight = vp.clientHeight - 2 * vpGap;\n\n if (availableWidth <= 0 || availableHeight <= 0) return false;\n\n let maxContentW = 0,\n maxContentH = 0;\n\n spreads.forEach((spread) => {\n const contentW = spread.reduce((s, p, i) => s + p.rotatedSize.width + (i ? pgGap : 0), 0);\n const contentH = Math.max(...spread.map((p) => p.rotatedSize.height));\n maxContentW = Math.max(maxContentW, contentW);\n maxContentH = Math.max(maxContentH, contentH);\n });\n\n switch (mode) {\n case ZoomMode.FitWidth:\n return availableWidth / maxContentW;\n case ZoomMode.FitPage:\n return Math.min(availableWidth / maxContentW, availableHeight / maxContentH);\n case ZoomMode.Automatic:\n return Math.min(availableWidth / maxContentW, 1);\n default:\n return 1;\n }\n }\n\n private computeScrollForZoomChange(\n documentId: string,\n vp: ViewportMetrics,\n oldZoom: number,\n newZoom: number,\n focus: Point,\n align: 'keep' | 'center' = 'keep',\n ) {\n const scrollScope = this.scroll.forDocument(documentId);\n const layout = scrollScope.getLayout();\n const vpGap = this.viewport.getViewportGap();\n\n const contentW = layout.totalContentSize.width;\n const contentH = layout.totalContentSize.height;\n\n const availableWidth = vp.clientWidth - 2 * vpGap;\n const availableHeight = vp.clientHeight - 2 * vpGap;\n\n const off = (availableSpace: number, cw: number, zoom: number) =>\n cw * zoom < availableSpace ? (availableSpace - cw * zoom) / 2 : 0;\n\n const offXold = off(availableWidth, contentW, oldZoom);\n const offYold = off(availableHeight, contentH, oldZoom);\n\n const offXnew = off(availableWidth, contentW, newZoom);\n const offYnew = off(availableHeight, contentH, newZoom);\n\n const cx = (vp.scrollLeft + focus.vx - vpGap - offXold) / oldZoom;\n const cy = (vp.scrollTop + focus.vy - vpGap - offYold) / oldZoom;\n\n const baseLeft = cx * newZoom + vpGap + offXnew;\n const baseTop = cy * newZoom + vpGap + offYnew;\n\n const desiredScrollLeft =\n align === 'center' ? baseLeft - vp.clientWidth / 2 : baseLeft - focus.vx;\n const desiredScrollTop =\n align === 'center' ? baseTop - vp.clientHeight / 2 : baseTop - focus.vy;\n\n return {\n desiredScrollLeft: Math.max(0, desiredScrollLeft),\n desiredScrollTop: Math.max(0, desiredScrollTop),\n };\n }\n\n private handleZoomToArea(documentId: string, pageIndex: number, rect: Rect) {\n const coreDoc = this.coreState.core.documents[documentId];\n if (!coreDoc) return;\n\n const rotation = coreDoc.rotation;\n const viewport = this.viewport.forDocument(documentId);\n const vp = viewport.getMetrics();\n const vpGap = this.viewport.getViewportGap();\n const docState = this.getDocumentStateOrThrow(documentId);\n const oldZ = docState.currentZoomLevel;\n\n const availableW = vp.clientWidth - 2 * vpGap;\n const availableH = vp.clientHeight - 2 * vpGap;\n\n const scrollScope = this.scroll.forDocument(documentId);\n const layout = scrollScope.getLayout();\n\n const vItem = layout.virtualItems.find((it) =>\n it.pageLayouts.some((p) => p.pageIndex === pageIndex),\n );\n if (!vItem) return;\n\n const pageRel = vItem.pageLayouts.find((p) => p.pageIndex === pageIndex)!;\n\n const rotatedRect = rotateRect(\n { width: pageRel.width, height: pageRel.height },\n rect,\n rotation,\n );\n\n const targetZoom = this.toZoom(\n Math.min(availableW / rotatedRect.size.width, availableH / rotatedRect.size.height),\n );\n\n const pageAbsX = vItem.x + pageRel.x;\n const pageAbsY = vItem.y + pageRel.y;\n\n const cxContent = pageAbsX + rotatedRect.origin.x + rotatedRect.size.width / 2;\n const cyContent = pageAbsY + rotatedRect.origin.y + rotatedRect.size.height / 2;\n\n const off = (avail: number, cw: number, z: number) =>\n cw * z < avail ? (avail - cw * z) / 2 : 0;\n\n const offXold = off(availableW, layout.totalContentSize.width, oldZ);\n const offYold = off(availableH, layout.totalContentSize.height, oldZ);\n\n const centerVX = vpGap + offXold + cxContent * oldZ - vp.scrollLeft;\n const centerVY = vpGap + offYold + cyContent * oldZ - vp.scrollTop;\n\n this.handleRequest(\n {\n level: targetZoom,\n center: { vx: centerVX, vy: centerVY },\n align: 'center',\n },\n documentId,\n );\n }\n\n private recalcAuto(documentId: string, focus?: VerticalZoomFocus) {\n const docState = this.getDocumentState(documentId);\n if (!docState) return;\n\n if (\n docState.zoomLevel === ZoomMode.Automatic ||\n docState.zoomLevel === ZoomMode.FitPage ||\n docState.zoomLevel === ZoomMode.FitWidth\n ) {\n this.handleRequest({ level: docState.zoomLevel, focus }, documentId);\n }\n }\n\n // ─────────────────────────────────────────────────────────\n // Helpers\n // ─────────────────────────────────────────────────────────\n\n private normalizeRanges(ranges: ZoomRangeStep[]): ZoomRangeStep[] {\n return [...ranges].filter((r) => r.step > 0 && r.max > r.min).sort((a, b) => a.min - b.min);\n }\n\n private stepFor(zoom: number): number {\n const r = this.zoomRanges.find((r) => zoom >= r.min && zoom < r.max);\n return r ? r.step : this.zoomStep;\n }\n\n private toZoom(v: number) {\n return parseFloat(clamp(v, this.minZoom, this.maxZoom).toFixed(2));\n }\n\n // ─────────────────────────────────────────────────────────\n // Marquee Zoom\n // ─────────────────────────────────────────────────────────\n\n public registerMarqueeOnPage(opts: RegisterMarqueeOnPageOptions) {\n if (!this.interactionManager) {\n this.logger.warn(\n 'ZoomPlugin',\n 'MissingDependency',\n 'Interaction manager plugin not loaded, marquee zoom disabled',\n );\n return () => {};\n }\n\n const coreDoc = this.coreState.core.documents[opts.documentId];\n if (!coreDoc || !coreDoc.document) {\n this.logger.warn('ZoomPlugin', 'DocumentNotFound', 'Document not found');\n return () => {};\n }\n\n const page = coreDoc.document.pages[opts.pageIndex];\n if (!page) {\n this.logger.warn('ZoomPlugin', 'PageNotFound', `Page ${opts.pageIndex} not found`);\n return () => {};\n }\n\n const handlers = createMarqueeHandler({\n pageSize: page.size,\n scale: opts.scale,\n onPreview: opts.callback.onPreview,\n onCommit: (rect) => {\n this.zoomToArea(opts.pageIndex, rect, opts.documentId);\n opts.callback.onCommit?.(rect);\n },\n onSmallDrag: () => {\n this.zoomIn(opts.documentId);\n opts.callback.onSmallDrag?.();\n },\n });\n\n const off = this.interactionManager.registerHandlers({\n documentId: opts.documentId,\n modeId: 'marqueeZoom',\n handlers,\n pageIndex: opts.pageIndex,\n });\n\n return off;\n }\n\n // ─────────────────────────────────────────────────────────\n // Store Update Handlers\n // ─────────────────────────────────────────────────────────\n\n override onStoreUpdated(prevState: ZoomState, newState: ZoomState): void {\n // Emit state changes for each changed document\n for (const documentId in newState.documents) {\n const prevDoc = prevState.documents[documentId];\n const newDoc = newState.documents[documentId];\n\n if (\n prevDoc &&\n newDoc &&\n (prevDoc.currentZoomLevel !== newDoc.currentZoomLevel ||\n prevDoc.zoomLevel !== newDoc.zoomLevel ||\n prevDoc.isMarqueeZoomActive !== newDoc.isMarqueeZoomActive)\n ) {\n this.state$.emit({\n documentId,\n state: newDoc,\n });\n }\n }\n }\n\n // ─────────────────────────────────────────────────────────\n // Lifecycle\n // ─────────────────────────────────────────────────────────\n\n async initialize(): Promise<void> {\n this.logger.info('ZoomPlugin', 'Initialize', 'Zoom plugin initialized');\n }\n\n async destroy() {\n this.zoom$.clear();\n this.state$.clear();\n super.destroy();\n }\n}\n","import { PluginPackage } from '@embedpdf/core';\n\nimport { ZoomAction } from './actions';\nimport { manifest, ZOOM_PLUGIN_ID } from './manifest';\nimport { zoomReducer, initialState, initialDocumentState } from './reducer';\nimport { ZoomPluginConfig, ZoomState } from './types';\nimport { ZoomPlugin } from './zoom-plugin';\n\nexport const ZoomPluginPackage: PluginPackage<ZoomPlugin, ZoomPluginConfig, ZoomState, ZoomAction> =\n {\n manifest,\n create: (registry, config) => new ZoomPlugin(ZOOM_PLUGIN_ID, registry, config),\n reducer: zoomReducer,\n initialState,\n };\n\nexport * from './zoom-plugin';\nexport * from './types';\nexport * from './manifest';\nexport { initialState, initialDocumentState };\n"],"names":["ZoomMode","VerticalZoomFocus","r"],"mappings":";;AAQO,IAAK,6BAAAA,cAAL;AACLA,YAAA,WAAA,IAAY;AACZA,YAAA,SAAA,IAAU;AACVA,YAAA,UAAA,IAAW;AAHD,SAAAA;AAAA,GAAA,YAAA,CAAA,CAAA;AA8HL,IAAK,sCAAAC,uBAAL;AACLA,qBAAAA,mBAAA,QAAA,IAAA,CAAA,IAAA;AACAA,qBAAAA,mBAAA,KAAA,IAAA,CAAA,IAAA;AAFU,SAAAA;AAAA,GAAA,qBAAA,CAAA,CAAA;AClIL,MAAM,iBAAiB;AAEvB,MAAM,WAA6C;AAAA,EACxD,IAAI;AAAA,EACJ,MAAM;AAAA,EACN,SAAS;AAAA,EACT,UAAU,CAAC,MAAM;AAAA,EACjB,UAAU,CAAC,YAAY,QAAQ;AAAA,EAC/B,UAAU,CAAC,uBAAuB,QAAQ;AAAA,EAC1C,eAAe;AAAA,IACb,kBAAkB,SAAS;AAAA,IAC3B,SAAS;AAAA,IACT,SAAS;AAAA,IACT,UAAU;AAAA,IACV,YAAY;AAAA,MACV;AAAA,QACE,KAAK;AAAA,QACL,KAAK;AAAA,QACL,MAAM;AAAA,MAAA;AAAA,MAER;AAAA,QACE,KAAK;AAAA,QACL,KAAK;AAAA,QACL,MAAM;AAAA,MAAA;AAAA,MAER;AAAA,QACE,KAAK;AAAA,QACL,KAAK;AAAA,QACL,MAAM;AAAA,MAAA;AAAA,MAER;AAAA,QACE,KAAK;AAAA,QACL,KAAK;AAAA,QACL,MAAM;AAAA,MAAA;AAAA,MAER;AAAA,QACE,KAAK;AAAA,QACL,KAAK;AAAA,QACL,MAAM;AAAA,MAAA;AAAA,MAER;AAAA,QACE,KAAK;AAAA,QACL,KAAK;AAAA,QACL,MAAM;AAAA,MAAA;AAAA,MAER;AAAA,QACE,KAAK;AAAA,QACL,KAAK;AAAA,QACL,MAAM;AAAA,MAAA;AAAA,MAER;AAAA,QACE,KAAK;AAAA,QACL,KAAK;AAAA,QACL,MAAM;AAAA,MAAA;AAAA,IACR;AAAA,IAEF,SAAS;AAAA,MACP;AAAA,QACE,MAAM;AAAA,QACN,OAAO,SAAS;AAAA,MAAA;AAAA,MAElB;AAAA,QACE,MAAM;AAAA,QACN,OAAO,SAAS;AAAA,MAAA;AAAA,MAElB;AAAA,QACE,MAAM;AAAA,QACN,OAAO,SAAS;AAAA,MAAA;AAAA,MAElB;AAAA,QACE,MAAM;AAAA,QACN,OAAO;AAAA,MAAA;AAAA,MAET;AAAA,QACE,MAAM;AAAA,QACN,OAAO;AAAA,MAAA;AAAA,MAET;AAAA,QACE,MAAM;AAAA,QACN,OAAO;AAAA,MAAA;AAAA,MAET;AAAA,QACE,MAAM;AAAA,QACN,OAAO;AAAA,MAAA;AAAA,MAET;AAAA,QACE,MAAM;AAAA,QACN,OAAO;AAAA,MAAA;AAAA,MAET;AAAA,QACE,MAAM;AAAA,QACN,OAAO;AAAA,MAAA;AAAA,MAET;AAAA,QACE,MAAM;AAAA,QACN,OAAO;AAAA,MAAA;AAAA,MAET;AAAA,QACE,MAAM;AAAA,QACN,OAAO;AAAA,MAAA;AAAA,MAET;AAAA,QACE,MAAM;AAAA,QACN,OAAO;AAAA,MAAA;AAAA,IACT;AAAA,EACF;AAEJ;AC3GO,MAAM,kBAAkB;AACxB,MAAM,qBAAqB;AAC3B,MAAM,sBAAsB;AAG5B,MAAM,iBAAiB;AACvB,MAAM,0BAA0B;AA8ChC,SAAS,cAAc,YAAoB,OAA+C;AAC/F,SAAO,EAAE,MAAM,iBAAiB,SAAS,EAAE,YAAY,QAAM;AAC/D;AAEO,SAAS,iBAAiB,YAA4C;AAC3E,SAAO,EAAE,MAAM,oBAAoB,SAAS,WAAA;AAC9C;AAMO,SAAS,aACd,YACA,WACA,kBACoB;AACpB,SAAO,EAAE,MAAM,gBAAgB,SAAS,EAAE,YAAY,WAAW,mBAAiB;AACpF;AAEO,SAAS,qBACd,YACA,UAC4B;AAC5B,SAAO,EAAE,MAAM,yBAAyB,SAAS,EAAE,YAAY,WAAS;AAC1E;ACtEO,MAAM,uBAA0C;AAAA,EACrD,WAAW,SAAS;AAAA,EACpB,kBAAkB;AAAA,EAClB,qBAAqB;AACvB;AAEO,MAAM,eAA0B;AAAA,EACrC,WAAW,CAAA;AAAA,EACX,kBAAkB;AACpB;AAEO,MAAM,cAA8C,CAAC,QAAQ,cAAc,WAAW;AAC3F,UAAQ,OAAO,MAAA;AAAA,IACb,KAAK,iBAAiB;AACpB,YAAM,EAAE,YAAY,OAAO,SAAA,IAAa,OAAO;AAC/C,aAAO;AAAA,QACL,GAAG;AAAA,QACH,WAAW;AAAA,UACT,GAAG,MAAM;AAAA,UACT,CAAC,UAAU,GAAG;AAAA,QAAA;AAAA;AAAA,QAGhB,kBAAkB,MAAM,oBAAoB;AAAA,MAAA;AAAA,IAEhD;AAAA,IAEA,KAAK,oBAAoB;AACvB,YAAM,aAAa,OAAO;AAC1B,YAAM,EAAE,CAAC,UAAU,GAAG,SAAS,GAAG,cAAA,IAAkB,MAAM;AAC1D,aAAO;AAAA,QACL,GAAG;AAAA,QACH,WAAW;AAAA,QACX,kBAAkB,MAAM,qBAAqB,aAAa,OAAO,MAAM;AAAA,MAAA;AAAA,IAE3E;AAAA,IAEA,KAAK,qBAAqB;AACxB,aAAO;AAAA,QACL,GAAG;AAAA,QACH,kBAAkB,OAAO;AAAA,MAAA;AAAA,IAE7B;AAAA,IAEA,KAAK,gBAAgB;AACnB,YAAM,EAAE,YAAY,WAAW,iBAAA,IAAqB,OAAO;AAC3D,YAAM,WAAW,MAAM,UAAU,UAAU;AAC3C,UAAI,CAAC,SAAU,QAAO;AAEtB,aAAO;AAAA,QACL,GAAG;AAAA,QACH,WAAW;AAAA,UACT,GAAG,MAAM;AAAA,UACT,CAAC,UAAU,GAAG;AAAA,YACZ,GAAG;AAAA,YACH;AAAA,YACA;AAAA,UAAA;AAAA,QACF;AAAA,MACF;AAAA,IAEJ;AAAA,IAEA,KAAK,yBAAyB;AAC5B,YAAM,EAAE,YAAY,SAAA,IAAa,OAAO;AACxC,YAAM,WAAW,MAAM,UAAU,UAAU;AAC3C,UAAI,CAAC,SAAU,QAAO;AAEtB,aAAO;AAAA,QACL,GAAG;AAAA,QACH,WAAW;AAAA,UACT,GAAG,MAAM;AAAA,UACT,CAAC,UAAU,GAAG;AAAA,YACZ,GAAG;AAAA,YACH,qBAAqB;AAAA,UAAA;AAAA,QACvB;AAAA,MACF;AAAA,IAEJ;AAAA,IAEA;AACE,aAAO;AAAA,EAAA;AAEb;ACrFO,SAAS,qBAAqB,MAOuB;AAC1D,QAAM,EAAE,UAAU,OAAO,YAAY,GAAG,WAAW,UAAU,gBAAgB;AAE7E,MAAI,QAAyB;AAC7B,MAAI,OAAoB;AAExB,SAAO;AAAA,IACL,eAAe,CAAC,KAAK,QAAQ;;AAC3B,cAAQ;AACR,aAAO,EAAE,QAAQ,EAAE,GAAG,IAAI,GAAG,GAAG,IAAI,EAAA,GAAK,MAAM,EAAE,OAAO,GAAG,QAAQ,IAAE;AACrE,6CAAY;AACZ,gBAAI,sBAAJ;AAAA,IACF;AAAA,IACA,eAAe,CAAC,QAAQ;AACtB,UAAI,CAAC,MAAO;AACZ,YAAM,IAAI,MAAM,IAAI,GAAG,GAAG,SAAS,KAAK;AACxC,YAAM,IAAI,MAAM,IAAI,GAAG,GAAG,SAAS,MAAM;AACzC,aAAO;AAAA,QACL,QAAQ,EAAE,GAAG,KAAK,IAAI,MAAM,GAAG,CAAC,GAAG,GAAG,KAAK,IAAI,MAAM,GAAG,CAAC,EAAA;AAAA,QACzD,MAAM,EAAE,OAAO,KAAK,IAAI,IAAI,MAAM,CAAC,GAAG,QAAQ,KAAK,IAAI,IAAI,MAAM,CAAC,EAAA;AAAA,MAAE;AAEtE,6CAAY;AAAA,IACd;AAAA,IACA,aAAa,CAAC,MAAM,QAAQ;;AAC1B,UAAI,MAAM;AACR,cAAM,SAAS,KAAK,IAAI,KAAK,KAAK,OAAO,KAAK,KAAK,MAAM,IAAI;AAC7D,YAAI,SAAS,WAAW;AACtB,+CAAW;AAAA,QACb,OAAO;AACL;AAAA,QACF;AAAA,MACF;AACA,cAAQ;AACR,aAAO;AACP,6CAAY;AACZ,gBAAI,0BAAJ;AAAA,IACF;AAAA,IACA,iBAAiB,CAAC,MAAM,QAAQ;;AAC9B,cAAQ;AACR,aAAO;AACP,6CAAY;AACZ,gBAAI,0BAAJ;AAAA,IACF;AAAA,EAAA;AAEJ;ACdO,MAAM,cAAN,MAAM,oBAAmB,WAK9B;AAAA,EAkBA,YAAY,IAAY,UAA0B,KAAuB;;AACvE,UAAM,IAAI,QAAQ;AAhBpB,SAAiB,QAAQ,cAAA;AACzB,SAAiB,SAAS,sBAAA;AAiBxB,SAAK,iBAAiB,SAAS,UAA0B,UAAU;AACnE,SAAK,WAAW,KAAK,eAAe,SAAA;AACpC,SAAK,SAAS,SAAS,UAAwB,QAAQ,EAAG,SAAA;AAC1D,UAAM,qBAAqB,SAAS,UAAoC,qBAAqB;AAC7F,SAAK,sBAAqB,yDAAoB,eAAc;AAC5D,UAAM,SAAS,SAAS,UAAwB,QAAQ;AACxD,SAAK,UAAS,iCAAQ,eAAc;AAEpC,SAAK,UAAU,IAAI,WAAW;AAC9B,SAAK,UAAU,IAAI,WAAW;AAC9B,SAAK,WAAW,IAAI,YAAY;AAChC,SAAK,mBAAmB,IAAI;AAC5B,SAAK,UAAU,IAAI,WAAW,CAAA;AAC9B,SAAK,aAAa,KAAK,gBAAgB,IAAI,cAAc,EAAE;AAG3D,SAAK,SAAS;AAAA,MACZ,CAAC,UAAU,KAAK,WAAW,MAAM,YAAY,kBAAkB,GAAG;AAAA,MAClE;AAAA,QACE,MAAM;AAAA,QACN,MAAM;AAAA,QACN,cAAc,CAAC,UAAU,MAAM;AAAA,MAAA;AAAA,IACjC;AAIF,eAAK,WAAL,mBAAa,eAAe,CAAC,UAAU;AACrC,WAAK,WAAW,MAAM,YAAY,kBAAkB,GAAG;AAAA,IACzD;AAGA,eAAK,uBAAL,mBAAyB,aAAa;AAAA,MACpC,IAAI;AAAA,MACJ,OAAO;AAAA,MACP,WAAW;AAAA,MACX,QAAQ;AAAA,IAAA;AAGV,eAAK,uBAAL,mBAAyB,aAAa,CAAC,UAAU;AAE/C,YAAM,kBAAkB,MAAM,eAAe;AAC7C,YAAM,WAAW,KAAK,iBAAiB,MAAM,UAAU;AAGvD,UAAI,YAAY,SAAS,wBAAwB,iBAAiB;AAChE,aAAK,SAAS,qBAAqB,MAAM,YAAY,eAAe,CAAC;AAAA,MACvE;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAMmB,yBAAyB,YAA0B;AACpE,SAAK,SAAS,KAAK,QAAQ,UAAU;AAErC,UAAM,WAA8B;AAAA,MAClC,GAAG;AAAA,MACH,WAAW,KAAK;AAAA,IAAA;AAGlB,SAAK,SAAS,cAAc,YAAY,QAAQ,CAAC;AAEjD,SAAK,OAAO;AAAA,MACV;AAAA,MACA;AAAA,MACA,wCAAwC,UAAU;AAAA,IAAA;AAAA,EAEtD;AAAA,EAEmB,iBAAiB,YAA0B;AAE5D,SAAK,WAAW,YAAY,kBAAkB,GAAG;AAAA,EACnD;AAAA,EAEmB,iBAAiB,YAA0B;AAC5D,SAAK,SAAS,iBAAiB,UAAU,CAAC;AAE1C,SAAK,OAAO;AAAA,MACV;AAAA,MACA;AAAA,MACA,uCAAuC,UAAU;AAAA,IAAA;AAAA,EAErD;AAAA,EAEmB,kBAAkB,YAA0B;AAE7D,SAAK,WAAW,YAAY,kBAAkB,GAAG;AAAA,EACnD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAYU,kBAAkC;AAC1C,WAAO;AAAA;AAAA,MAEL,aAAa,CAAC,OAAO,MAAM,KAAK,YAAY,OAAO,CAAC;AAAA,MACpD,eAAe,CAAC,GAAG,MAAM,KAAK,cAAc,GAAG,CAAC;AAAA,MAChD,QAAQ,MAAM,KAAK,OAAA;AAAA,MACnB,SAAS,MAAM,KAAK,QAAA;AAAA,MACpB,YAAY,CAAC,WAAW,SAAS,KAAK,WAAW,WAAW,IAAI;AAAA,MAChE,mBAAmB,MAAM,KAAK,kBAAA;AAAA,MAC9B,oBAAoB,MAAM,KAAK,mBAAA;AAAA,MAC/B,mBAAmB,MAAM,KAAK,kBAAA;AAAA,MAC9B,qBAAqB,MAAM,KAAK,oBAAA;AAAA,MAChC,UAAU,MAAM,KAAK,wBAAA;AAAA;AAAA,MAGrB,aAAa,CAAC,eAAuB,KAAK,gBAAgB,UAAU;AAAA;AAAA,MAGpE,uBAAuB,CAAC,SAAS,KAAK,sBAAsB,IAAI;AAAA,MAChE,YAAY,MAAM,KAAK;AAAA;AAAA,MAGvB,cAAc,KAAK,MAAM;AAAA,MACzB,eAAe,KAAK,OAAO;AAAA,IAAA;AAAA,EAE/B;AAAA;AAAA;AAAA;AAAA,EAMQ,gBAAgB,YAA+B;AACrD,WAAO;AAAA,MACL,aAAa,CAAC,OAAO,MAAM,KAAK,YAAY,OAAO,GAAG,UAAU;AAAA,MAChE,eAAe,CAAC,GAAG,MAAM,KAAK,cAAc,GAAG,GAAG,UAAU;AAAA,MAC5D,QAAQ,MAAM,KAAK,OAAO,UAAU;AAAA,MACpC,SAAS,MAAM,KAAK,QAAQ,UAAU;AAAA,MACtC,YAAY,CAAC,WAAW,SAAS,KAAK,WAAW,WAAW,MAAM,UAAU;AAAA,MAC5E,mBAAmB,MAAM,KAAK,kBAAkB,UAAU;AAAA,MAC1D,oBAAoB,MAAM,KAAK,mBAAmB,UAAU;AAAA,MAC5D,mBAAmB,MAAM,KAAK,kBAAkB,UAAU;AAAA,MAC1D,qBAAqB,MAAM,KAAK,oBAAoB,UAAU;AAAA,MAC9D,UAAU,MAAM,KAAK,wBAAwB,UAAU;AAAA,MACvD,cAAc,CAAC,aACb,KAAK,MAAM,GAAG,CAAC,UAAU;AACvB,YAAI,MAAM,eAAe,WAAY,UAAS,KAAK;AAAA,MACrD,CAAC;AAAA,MACH,eAAe,CAAC,aACd,KAAK,OAAO,GAAG,CAAC,UAAU;AACxB,YAAI,MAAM,eAAe,WAAY,UAAS,MAAM,KAAK;AAAA,MAC3D,CAAC;AAAA,IAAA;AAAA,EAEP;AAAA;AAAA;AAAA;AAAA,EAMQ,iBAAiB,YAA+C;AACtE,UAAM,KAAK,cAAc,KAAK,oBAAA;AAC9B,WAAO,KAAK,MAAM,UAAU,EAAE,KAAK;AAAA,EACrC;AAAA,EAEQ,wBAAwB,YAAwC;AACtE,UAAM,QAAQ,KAAK,iBAAiB,UAAU;AAC9C,QAAI,CAAC,OAAO;AACV,YAAM,IAAI,MAAM,sCAAsC,cAAc,QAAQ,EAAE;AAAA,IAChF;AACA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAMQ,YAAY,OAA0B,QAAgB,YAA2B;AACvF,SAAK,cAAc,EAAE,OAAO,OAAA,GAAU,UAAU;AAAA,EAClD;AAAA,EAEQ,cAAc,OAAe,QAAgB,YAA2B;AAC9E,UAAM,KAAK,cAAc,KAAK,oBAAA;AAC9B,UAAM,WAAW,KAAK,wBAAwB,EAAE;AAChD,UAAM,MAAM,SAAS;AACrB,UAAM,SAAS,KAAK,OAAO,MAAM,KAAK;AACtC,SAAK,cAAc,EAAE,OAAO,QAAQ,OAAA,GAAU,EAAE;AAAA,EAClD;AAAA,EAEQ,OAAO,YAA2B;AACxC,UAAM,KAAK,cAAc,KAAK,oBAAA;AAC9B,UAAM,WAAW,KAAK,wBAAwB,EAAE;AAChD,UAAM,MAAM,SAAS;AACrB,SAAK,cAAc,EAAE,OAAO,KAAK,OAAO,KAAK,QAAQ,GAAG,EAAA,GAAK,EAAE;AAAA,EACjE;AAAA,EAEQ,QAAQ,YAA2B;AACzC,UAAM,KAAK,cAAc,KAAK,oBAAA;AAC9B,UAAM,WAAW,KAAK,wBAAwB,EAAE;AAChD,UAAM,MAAM,SAAS;AACrB,SAAK,cAAc,EAAE,OAAO,KAAK,OAAO,CAAC,KAAK,QAAQ,GAAG,EAAA,GAAK,EAAE;AAAA,EAClE;AAAA,EAEQ,WAAW,WAAmB,MAAY,YAA2B;AAC3E,UAAM,KAAK,cAAc,KAAK,oBAAA;AAC9B,SAAK,iBAAiB,IAAI,WAAW,IAAI;AAAA,EAC3C;AAAA,EAEQ,kBAAkB,YAA2B;;AACnD,UAAM,KAAK,cAAc,KAAK,oBAAA;AAC9B,eAAK,uBAAL,mBAAyB,YAAY,IAAI,SAAS;AAAA,EACpD;AAAA,EAEQ,mBAAmB,YAA2B;;AACpD,UAAM,KAAK,cAAc,KAAK,oBAAA;AAC9B,eAAK,uBAAL,mBAAyB,YAAY,IAAI;AAAA,EAC3C;AAAA,EAEQ,kBAAkB,YAA2B;;AACnD,UAAM,KAAK,cAAc,KAAK,oBAAA;AAC9B,UAAM,SAAQ,UAAK,uBAAL,mBAAyB,YAAY;AACnD,SAAI,+BAAO,qBAAoB,eAAe;AAC5C,YAAM,oBAAA;AAAA,IACR,OAAO;AACL,qCAAO,SAAS;AAAA,IAClB;AAAA,EACF;AAAA,EAEQ,oBAAoB,YAA8B;;AACxD,UAAM,KAAK,cAAc,KAAK,oBAAA;AAC9B,aAAO,UAAK,uBAAL,mBAAyB,YAAY,IAAI,qBAAoB;AAAA,EACtE;AAAA;AAAA;AAAA;AAAA,EAMQ,cACN,EAAE,OAAO,QAAQ,GAAG,QAAQ,QAAQ,kBAAkB,QAAQ,QAAQ,OAAA,GACtE,YACA;AACA,UAAM,KAAK,cAAc,KAAK,oBAAA;AAC9B,UAAM,WAAW,KAAK,wBAAwB,EAAE;AAChD,UAAM,UAAU,KAAK,UAAU,KAAK,UAAU,EAAE;AAChD,QAAI,CAAC,QAAS;AAEd,UAAM,WAAW,KAAK,SAAS,YAAY,EAAE;AAC7C,UAAM,UAAU,SAAS,WAAA;AACzB,UAAM,UAAU,SAAS;AAEzB,QAAI,QAAQ,gBAAgB,KAAK,QAAQ,iBAAiB,GAAG;AAC3D;AAAA,IACF;AAGA,UAAM,OAAO,OAAO,UAAU,WAAW,QAAQ,KAAK,mBAAmB,IAAI,OAAO,OAAO;AAE3F,QAAI,SAAS,MAAO;AAEpB,UAAM,YAAY,MAAM,OAAO,OAAO,KAAK,SAAS,KAAK,OAAO;AAChE,UAAM,UAAU,KAAK,MAAM,YAAY,GAAI,IAAI;AAG/C,UAAM,aAAoB,UAAU;AAAA,MAClC,IAAI,QAAQ,cAAc;AAAA,MAC1B,IAAI,UAAU,kBAAkB,MAAM,IAAI,QAAQ,eAAe;AAAA,IAAA;AAInE,UAAM,EAAE,mBAAmB,iBAAA,IAAqB,KAAK;AAAA,MACnD;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IAAA;AAIF,QAAI,CAAC,MAAM,iBAAiB,KAAK,CAAC,MAAM,gBAAgB,GAAG;AACzD,WAAK,eAAe,yBAAyB,IAAI;AAAA,QAC/C,YAAY;AAAA,QACZ,WAAW;AAAA,MAAA,CACZ;AAAA,IACH;AAEA,SAAK,SAAS,aAAa,IAAI,OAAO,UAAU,WAAW,UAAU,OAAO,OAAO,CAAC;AACpF,SAAK,mBAAmB,SAAS,SAAS,EAAE,CAAC;AAC7C,QAAI,KAAK,SAAS,QAAQ,EAAE,GAAG;AAC7B,WAAK,SAAS,YAAY,QAAQ,EAAE;AAAA,IACtC;AAEA,aAAS,SAAS;AAAA,MAChB,GAAG;AAAA,MACH,GAAG;AAAA,MACH,UAAU;AAAA,IAAA,CACX;AAED,UAAM,MAAuB;AAAA,MAC3B,YAAY;AAAA,MACZ;AAAA,MACA;AAAA,MACA;AAAA,MACA,QAAQ;AAAA,MACR;AAAA,MACA;AAAA,MACA,UAAU;AAAA,IAAA;AAGZ,SAAK,MAAM,KAAK,GAAG;AAAA,EACrB;AAAA,EAEQ,mBACN,YACA,MACA,IACgB;AAChB,UAAM,UAAU,KAAK,UAAU,KAAK,UAAU,UAAU;AACxD,QAAI,CAAC,QAAS,QAAO;AAErB,UAAM,cAAc,KAAK,OAAO,YAAY,UAAU;AACtD,UAAM,QAAQ,cAAc,KAAK,OAAO,eAAe;AACvD,UAAM,QAAQ,KAAK,SAAS,eAAA;AAE5B,UAAM,UAAU,YAAY,8BAAA;AAC5B,QAAI,CAAC,QAAQ,OAAQ,QAAO;AAE5B,QAAI,GAAG,gBAAgB,KAAK,GAAG,iBAAiB,EAAG,QAAO;AAE1D,UAAM,iBAAiB,GAAG,cAAc,IAAI;AAC5C,UAAM,kBAAkB,GAAG,eAAe,IAAI;AAE9C,QAAI,kBAAkB,KAAK,mBAAmB,EAAG,QAAO;AAExD,QAAI,cAAc,GAChB,cAAc;AAEhB,YAAQ,QAAQ,CAAC,WAAW;AAC1B,YAAM,WAAW,OAAO,OAAO,CAAC,GAAG,GAAG,MAAM,IAAI,EAAE,YAAY,SAAS,IAAI,QAAQ,IAAI,CAAC;AACxF,YAAM,WAAW,KAAK,IAAI,GAAG,OAAO,IAAI,CAAC,MAAM,EAAE,YAAY,MAAM,CAAC;AACpE,oBAAc,KAAK,IAAI,aAAa,QAAQ;AAC5C,oBAAc,KAAK,IAAI,aAAa,QAAQ;AAAA,IAC9C,CAAC;AAED,YAAQ,MAAA;AAAA,MACN,KAAK,SAAS;AACZ,eAAO,iBAAiB;AAAA,MAC1B,KAAK,SAAS;AACZ,eAAO,KAAK,IAAI,iBAAiB,aAAa,kBAAkB,WAAW;AAAA,MAC7E,KAAK,SAAS;AACZ,eAAO,KAAK,IAAI,iBAAiB,aAAa,CAAC;AAAA,MACjD;AACE,eAAO;AAAA,IAAA;AAAA,EAEb;AAAA,EAEQ,2BACN,YACA,IACA,SACA,SACA,OACA,QAA2B,QAC3B;AACA,UAAM,cAAc,KAAK,OAAO,YAAY,UAAU;AACtD,UAAM,SAAS,YAAY,UAAA;AAC3B,UAAM,QAAQ,KAAK,SAAS,eAAA;AAE5B,UAAM,WAAW,OAAO,iBAAiB;AACzC,UAAM,WAAW,OAAO,iBAAiB;AAEzC,UAAM,iBAAiB,GAAG,cAAc,IAAI;AAC5C,UAAM,kBAAkB,GAAG,eAAe,IAAI;AAE9C,UAAM,MAAM,CAAC,gBAAwB,IAAY,SAC/C,KAAK,OAAO,kBAAkB,iBAAiB,KAAK,QAAQ,IAAI;AAElE,UAAM,UAAU,IAAI,gBAAgB,UAAU,OAAO;AACrD,UAAM,UAAU,IAAI,iBAAiB,UAAU,OAAO;AAEtD,UAAM,UAAU,IAAI,gBAAgB,UAAU,OAAO;AACrD,UAAM,UAAU,IAAI,iBAAiB,UAAU,OAAO;AAEtD,UAAM,MAAM,GAAG,aAAa,MAAM,KAAK,QAAQ,WAAW;AAC1D,UAAM,MAAM,GAAG,YAAY,MAAM,KAAK,QAAQ,WAAW;AAEzD,UAAM,WAAW,KAAK,UAAU,QAAQ;AACxC,UAAM,UAAU,KAAK,UAAU,QAAQ;AAEvC,UAAM,oBACJ,UAAU,WAAW,WAAW,GAAG,cAAc,IAAI,WAAW,MAAM;AACxE,UAAM,mBACJ,UAAU,WAAW,UAAU,GAAG,eAAe,IAAI,UAAU,MAAM;AAEvE,WAAO;AAAA,MACL,mBAAmB,KAAK,IAAI,GAAG,iBAAiB;AAAA,MAChD,kBAAkB,KAAK,IAAI,GAAG,gBAAgB;AAAA,IAAA;AAAA,EAElD;AAAA,EAEQ,iBAAiB,YAAoB,WAAmB,MAAY;AAC1E,UAAM,UAAU,KAAK,UAAU,KAAK,UAAU,UAAU;AACxD,QAAI,CAAC,QAAS;AAEd,UAAM,WAAW,QAAQ;AACzB,UAAM,WAAW,KAAK,SAAS,YAAY,UAAU;AACrD,UAAM,KAAK,SAAS,WAAA;AACpB,UAAM,QAAQ,KAAK,SAAS,eAAA;AAC5B,UAAM,WAAW,KAAK,wBAAwB,UAAU;AACxD,UAAM,OAAO,SAAS;AAEtB,UAAM,aAAa,GAAG,cAAc,IAAI;AACxC,UAAM,aAAa,GAAG,eAAe,IAAI;AAEzC,UAAM,cAAc,KAAK,OAAO,YAAY,UAAU;AACtD,UAAM,SAAS,YAAY,UAAA;AAE3B,UAAM,QAAQ,OAAO,aAAa;AAAA,MAAK,CAAC,OACtC,GAAG,YAAY,KAAK,CAAC,MAAM,EAAE,cAAc,SAAS;AAAA,IAAA;AAEtD,QAAI,CAAC,MAAO;AAEZ,UAAM,UAAU,MAAM,YAAY,KAAK,CAAC,MAAM,EAAE,cAAc,SAAS;AAEvE,UAAM,cAAc;AAAA,MAClB,EAAE,OAAO,QAAQ,OAAO,QAAQ,QAAQ,OAAA;AAAA,MACxC;AAAA,MACA;AAAA,IAAA;AAGF,UAAM,aAAa,KAAK;AAAA,MACtB,KAAK,IAAI,aAAa,YAAY,KAAK,OAAO,aAAa,YAAY,KAAK,MAAM;AAAA,IAAA;AAGpF,UAAM,WAAW,MAAM,IAAI,QAAQ;AACnC,UAAM,WAAW,MAAM,IAAI,QAAQ;AAEnC,UAAM,YAAY,WAAW,YAAY,OAAO,IAAI,YAAY,KAAK,QAAQ;AAC7E,UAAM,YAAY,WAAW,YAAY,OAAO,IAAI,YAAY,KAAK,SAAS;AAE9E,UAAM,MAAM,CAAC,OAAe,IAAY,MACtC,KAAK,IAAI,SAAS,QAAQ,KAAK,KAAK,IAAI;AAE1C,UAAM,UAAU,IAAI,YAAY,OAAO,iBAAiB,OAAO,IAAI;AACnE,UAAM,UAAU,IAAI,YAAY,OAAO,iBAAiB,QAAQ,IAAI;AAEpE,UAAM,WAAW,QAAQ,UAAU,YAAY,OAAO,GAAG;AACzD,UAAM,WAAW,QAAQ,UAAU,YAAY,OAAO,GAAG;AAEzD,SAAK;AAAA,MACH;AAAA,QACE,OAAO;AAAA,QACP,QAAQ,EAAE,IAAI,UAAU,IAAI,SAAA;AAAA,QAC5B,OAAO;AAAA,MAAA;AAAA,MAET;AAAA,IAAA;AAAA,EAEJ;AAAA,EAEQ,WAAW,YAAoB,OAA2B;AAChE,UAAM,WAAW,KAAK,iBAAiB,UAAU;AACjD,QAAI,CAAC,SAAU;AAEf,QACE,SAAS,cAAc,SAAS,aAChC,SAAS,cAAc,SAAS,WAChC,SAAS,cAAc,SAAS,UAChC;AACA,WAAK,cAAc,EAAE,OAAO,SAAS,WAAW,MAAA,GAAS,UAAU;AAAA,IACrE;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAMQ,gBAAgB,QAA0C;AAChE,WAAO,CAAC,GAAG,MAAM,EAAE,OAAO,CAAC,MAAM,EAAE,OAAO,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,KAAK,CAAC,GAAG,MAAM,EAAE,MAAM,EAAE,GAAG;AAAA,EAC5F;AAAA,EAEQ,QAAQ,MAAsB;AACpC,UAAM,IAAI,KAAK,WAAW,KAAK,CAACC,OAAM,QAAQA,GAAE,OAAO,OAAOA,GAAE,GAAG;AACnE,WAAO,IAAI,EAAE,OAAO,KAAK;AAAA,EAC3B;AAAA,EAEQ,OAAO,GAAW;AACxB,WAAO,WAAW,MAAM,GAAG,KAAK,SAAS,KAAK,OAAO,EAAE,QAAQ,CAAC,CAAC;AAAA,EACnE;AAAA;AAAA;AAAA;AAAA,EAMO,sBAAsB,MAAoC;AAC/D,QAAI,CAAC,KAAK,oBAAoB;AAC5B,WAAK,OAAO;AAAA,QACV;AAAA,QACA;AAAA,QACA;AAAA,MAAA;AAEF,aAAO,MAAM;AAAA,MAAC;AAAA,IAChB;AAEA,UAAM,UAAU,KAAK,UAAU,KAAK,UAAU,KAAK,UAAU;AAC7D,QAAI,CAAC,WAAW,CAAC,QAAQ,UAAU;AACjC,WAAK,OAAO,KAAK,cAAc,oBAAoB,oBAAoB;AACvE,aAAO,MAAM;AAAA,MAAC;AAAA,IAChB;AAEA,UAAM,OAAO,QAAQ,SAAS,MAAM,KAAK,SAAS;AAClD,QAAI,CAAC,MAAM;AACT,WAAK,OAAO,KAAK,cAAc,gBAAgB,QAAQ,KAAK,SAAS,YAAY;AACjF,aAAO,MAAM;AAAA,MAAC;AAAA,IAChB;AAEA,UAAM,WAAW,qBAAqB;AAAA,MACpC,UAAU,KAAK;AAAA,MACf,OAAO,KAAK;AAAA,MACZ,WAAW,KAAK,SAAS;AAAA,MACzB,UAAU,CAAC,SAAS;;AAClB,aAAK,WAAW,KAAK,WAAW,MAAM,KAAK,UAAU;AACrD,yBAAK,UAAS,aAAd,4BAAyB;AAAA,MAC3B;AAAA,MACA,aAAa,MAAM;;AACjB,aAAK,OAAO,KAAK,UAAU;AAC3B,yBAAK,UAAS,gBAAd;AAAA,MACF;AAAA,IAAA,CACD;AAED,UAAM,MAAM,KAAK,mBAAmB,iBAAiB;AAAA,MACnD,YAAY,KAAK;AAAA,MACjB,QAAQ;AAAA,MACR;AAAA,MACA,WAAW,KAAK;AAAA,IAAA,CACjB;AAED,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAMS,eAAe,WAAsB,UAA2B;AAEvE,eAAW,cAAc,SAAS,WAAW;AAC3C,YAAM,UAAU,UAAU,UAAU,UAAU;AAC9C,YAAM,SAAS,SAAS,UAAU,UAAU;AAE5C,UACE,WACA,WACC,QAAQ,qBAAqB,OAAO,oBACnC,QAAQ,cAAc,OAAO,aAC7B,QAAQ,wBAAwB,OAAO,sBACzC;AACA,aAAK,OAAO,KAAK;AAAA,UACf;AAAA,UACA,OAAO;AAAA,QAAA,CACR;AAAA,MACH;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAMA,MAAM,aAA4B;AAChC,SAAK,OAAO,KAAK,cAAc,cAAc,yBAAyB;AAAA,EACxE;AAAA,EAEA,MAAM,UAAU;AACd,SAAK,MAAM,MAAA;AACX,SAAK,OAAO,MAAA;AACZ,UAAM,QAAA;AAAA,EACR;AACF;AAplBE,YAAgB,KAAK;AANhB,IAAM,aAAN;ACpCA,MAAM,oBACX;AAAA,EACE;AAAA,EACA,QAAQ,CAAC,UAAU,WAAW,IAAI,WAAW,gBAAgB,UAAU,MAAM;AAAA,EAC7E,SAAS;AAAA,EACT;AACF;"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@embedpdf/plugin-zoom",
3
- "version": "2.0.0-next.0",
3
+ "version": "2.0.0-next.2",
4
4
  "type": "module",
5
5
  "license": "MIT",
6
6
  "main": "./dist/index.cjs",
@@ -36,18 +36,18 @@
36
36
  },
37
37
  "dependencies": {
38
38
  "hammerjs": "^2.0.8",
39
- "@embedpdf/models": "2.0.0-next.0"
39
+ "@embedpdf/models": "2.0.0-next.2"
40
40
  },
41
41
  "devDependencies": {
42
42
  "@types/hammerjs": "^2.0.46",
43
43
  "@types/react": "^18.2.0",
44
44
  "typescript": "^5.0.0",
45
+ "@embedpdf/core": "2.0.0-next.2",
46
+ "@embedpdf/plugin-scroll": "2.0.0-next.2",
45
47
  "@embedpdf/build": "1.1.0",
46
- "@embedpdf/core": "2.0.0-next.0",
47
- "@embedpdf/plugin-viewport": "2.0.0-next.0",
48
- "@embedpdf/plugin-scroll": "2.0.0-next.0",
49
- "@embedpdf/plugin-spread": "2.0.0-next.0",
50
- "@embedpdf/plugin-interaction-manager": "2.0.0-next.0"
48
+ "@embedpdf/plugin-viewport": "2.0.0-next.2",
49
+ "@embedpdf/plugin-interaction-manager": "2.0.0-next.2",
50
+ "@embedpdf/plugin-spread": "2.0.0-next.2"
51
51
  },
52
52
  "peerDependencies": {
53
53
  "react": ">=16.8.0",
@@ -55,9 +55,9 @@
55
55
  "preact": "^10.26.4",
56
56
  "vue": ">=3.2.0",
57
57
  "svelte": ">=5 <6",
58
- "@embedpdf/core": "2.0.0-next.0",
59
- "@embedpdf/plugin-viewport": "2.0.0-next.0",
60
- "@embedpdf/plugin-scroll": "2.0.0-next.0"
58
+ "@embedpdf/plugin-viewport": "2.0.0-next.2",
59
+ "@embedpdf/plugin-scroll": "2.0.0-next.2",
60
+ "@embedpdf/core": "2.0.0-next.2"
61
61
  },
62
62
  "files": [
63
63
  "dist",