@embedpdf/plugin-zoom 1.3.15 → 1.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +1 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/shared/components/index.d.ts +2 -0
- package/dist/shared/components/marquee-zoom.d.ts +13 -0
- package/dist/shared/components/pinch-wrapper.d.ts +7 -0
- package/dist/shared/hooks/index.d.ts +2 -0
- package/dist/shared/hooks/use-pinch-zoom.d.ts +3 -0
- package/dist/shared/hooks/use-zoom.d.ts +15 -0
- package/dist/shared/index.d.ts +3 -0
- package/dist/shared/utils/pinch-zoom-logic.d.ts +8 -0
- package/dist/shared-svelte/utils/pinch-zoom-logic.d.ts +8 -0
- package/dist/svelte/components/MarqueeZoom.svelte.d.ts +14 -0
- package/dist/svelte/components/PinchWrapper.svelte.d.ts +9 -0
- package/dist/svelte/components/index.d.ts +2 -0
- package/dist/svelte/hooks/index.d.ts +2 -0
- package/dist/svelte/hooks/use-pinch-zoom.svelte.d.ts +3 -0
- package/dist/svelte/hooks/use-zoom.svelte.d.ts +15 -0
- package/dist/svelte/index.cjs +2 -0
- package/dist/svelte/index.cjs.map +1 -0
- package/dist/svelte/index.d.ts +3 -0
- package/dist/svelte/index.js +125 -0
- package/dist/svelte/index.js.map +1 -0
- package/package.json +20 -12
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 a="zoom",n={id:a,name:"Zoom Plugin",version:"1.0.0",provides:["zoom"],requires:["viewport","scroll"],optional:["interaction-manager"],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="SET_ZOOM_LEVEL",l="SET_INITIAL_ZOOM_LEVEL";const s={zoomLevel:o.Automatic,currentZoomLevel:1};const m=class extends e.BasePlugin{constructor(t,o,a){var n;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 r=o.getPlugin("interaction-manager");var s;this.interactionManager=(null==r?void 0:r.provides())??null,this.minZoom=a.minZoom??.25,this.maxZoom=a.maxZoom??10,this.zoomStep=a.zoomStep??.1,this.presets=a.presets??[],this.zoomRanges=this.normalizeRanges(a.zoomRanges??[]),this.dispatch((s=a.defaultZoomLevel,{type:l,payload:{zoomLevel:s}})),this.viewport.onViewportResize((()=>this.recalcAuto(i.Top)),{mode:"debounce",wait:150}),this.coreStore.onAction(e.SET_ROTATION,(()=>this.recalcAuto(i.Top))),this.coreStore.onAction(e.SET_PAGES,(()=>this.recalcAuto(i.Top))),this.coreStore.onAction(e.SET_DOCUMENT,(()=>this.recalcAuto(i.Top))),null==(n=this.interactionManager)||n.registerMode({id:"marqueeZoom",scope:"page",exclusive:!0,cursor:"zoom-in"}),this.resetReady()}buildCapability(){return{onZoomChange:this.zoom$.on,onStateChange:this.state$.on,zoomIn:()=>this.zoomIn(),zoomOut:()=>this.zoomOut(),zoomToArea:(e,t)=>this.zoomToArea(e,t),requestZoom:(e,t)=>this.handleRequest({level:e,center:t}),requestZoomBy:(e,t)=>{const o=this.state.currentZoomLevel,i=this.toZoom(o+e);return this.handleRequest({level:i,center:t})},enableMarqueeZoom:()=>{var e;null==(e=this.interactionManager)||e.activate("marqueeZoom")},disableMarqueeZoom:()=>{var e;null==(e=this.interactionManager)||e.activateDefaultMode()},toggleMarqueeZoom:()=>{var e,t,o;"marqueeZoom"===(null==(e=this.interactionManager)?void 0:e.getActiveMode())?null==(t=this.interactionManager)||t.activateDefaultMode():null==(o=this.interactionManager)||o.activate("marqueeZoom")},isMarqueeZoomActive:()=>{var e;return"marqueeZoom"===(null==(e=this.interactionManager)?void 0:e.getActiveMode())},registerMarqueeOnPage:e=>this.registerMarqueeOnPage(e),getState:()=>this.state,getPresets:()=>this.presets}}zoomOut(){const e=this.state.currentZoomLevel;return this.handleRequest({level:e,delta:-this.stepFor(e)})}zoomIn(){const e=this.state.currentZoomLevel;return this.handleRequest({level:e,delta:this.stepFor(e)})}zoomToArea(e,t){this.handleZoomToArea(e,t)}async initialize(){}async destroy(){this.zoom$.clear()}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))}handleRequest({level:t,delta:o=0,center:a,focus:n=i.Center,align:l="keep"}){const s=this.viewport.getMetrics(),m=this.state.currentZoomLevel;if(0===s.clientWidth||0===s.clientHeight)return;const c="number"==typeof t?t:this.computeZoomForMode(t,s);if(!1===c)return;const h=e.clamp(c+o,this.minZoom,this.maxZoom),u=Math.floor(100*h)/100,d=a??{vx:s.clientWidth/2,vy:n===i.Top?0:s.clientHeight/2},{desiredScrollLeft:g,desiredScrollTop:p}=this.computeScrollForZoomChange(s,m,u,d,l);isNaN(g)||isNaN(p)||this.viewportPlugin.setViewportScrollMetrics({scrollLeft:g,scrollTop:p}),this.dispatch({type:r,payload:{zoomLevel:"number"==typeof t?u:t,currentZoomLevel:u}}),this.dispatchCoreAction(e.setScale(u)),this.markReady(),this.viewport.scrollTo({x:g,y:p,behavior:"instant"});const v={oldZoom:m,newZoom:u,level:t,center:d,desiredScrollLeft:g,desiredScrollTop:p,viewport:s};this.zoom$.emit(v)}computeZoomForMode(t,i){const a=e.getPagesWithRotatedSize(this.coreState.core);if(!a.length)return!1;const n=this.scroll.getPageGap(),r=this.viewport.getViewportGap();if(0===i.clientWidth||0===i.clientHeight)return!1;const l=i.clientWidth-2*r,s=i.clientHeight-2*r;if(l<=0||s<=0)return!1;let m=0,c=0;switch(a.forEach((e=>{const t=e.reduce(((e,t,o)=>e+t.rotatedSize.width+(o?n:0)),0),o=Math.max(...e.map((e=>e.rotatedSize.height)));m=Math.max(m,t),c=Math.max(c,o)})),t){case o.FitWidth:return l/m;case o.FitPage:return Math.min(l/m,s/c);case o.Automatic:return Math.min(l/m,1);default:return 1}}computeScrollForZoomChange(e,t,o,i,a="keep"){const n=this.scroll.getLayout(),r=this.viewport.getViewportGap(),l=n.totalContentSize.width,s=n.totalContentSize.height,m=e.clientWidth-2*r,c=e.clientHeight-2*r,h=(e,t,o)=>t*o<e?(e-t*o)/2:0,u=h(m,l,t),d=h(c,s,t),g=h(m,l,o),p=h(c,s,o),v=(e.scrollLeft+i.vx-r-u)/t*o+r+g,z=(e.scrollTop+i.vy-r-d)/t*o+r+p,Z="center"===a?v-e.clientWidth/2:v-i.vx,x="center"===a?z-e.clientHeight/2:z-i.vy;return{desiredScrollLeft:Math.max(0,Z),desiredScrollTop:Math.max(0,x)}}handleZoomToArea(e,o){const i=this.coreState.core.rotation,a=this.viewport.getMetrics(),n=this.viewport.getViewportGap(),r=this.state.currentZoomLevel,l=a.clientWidth-2*n,s=a.clientHeight-2*n,m=this.scroll.getLayout(),c=m.virtualItems.find((t=>t.pageLayouts.some((t=>t.pageIndex===e))));if(!c)return;const h=c.pageLayouts.find((t=>t.pageIndex===e)),u=t.rotateRect({width:h.width,height:h.height},o,i),d=this.toZoom(Math.min(l/u.size.width,s/u.size.height)),g=c.x+h.x,p=c.y+h.y,v=g+u.origin.x+u.size.width/2,z=p+u.origin.y+u.size.height/2,Z=(e,t,o)=>t*o<e?(e-t*o)/2:0,x=Z(l,m.totalContentSize.width,r),M=Z(s,m.totalContentSize.height,r),S=n+x+v*r-a.scrollLeft,f=n+M+z*r-a.scrollTop;this.handleRequest({level:d,center:{vx:S,vy:f},align:"center"})}recalcAuto(e){const t=this.state;t.zoomLevel!==o.Automatic&&t.zoomLevel!==o.FitPage&&t.zoomLevel!==o.FitWidth||this.handleRequest({level:t.zoomLevel,focus:e})}onStoreUpdated(e,t){this.state$.emit(t)}registerMarqueeOnPage(t){if(!this.interactionManager)return this.logger.warn("ZoomPlugin","MissingDependency","Interaction manager plugin not loaded, marquee zoom disabled"),()=>{};const o=this.coreState.core.document;if(!o)return this.logger.warn("ZoomPlugin","DocumentNotFound","Document not found"),()=>{};const i=o.pages[t.pageIndex];if(!i)return this.logger.warn("ZoomPlugin","PageNotFound",`Page ${t.pageIndex} not found`),()=>{};const a=function(t){const{pageSize:o,scale:i,minDragPx:a=5,onPreview:n,onCommit:r,onSmallDrag:l}=t;let s=null,m=null;return{onPointerDown:(e,t)=>{var o;s=e,m={origin:{x:e.x,y:e.y},size:{width:0,height:0}},null==n||n(m),null==(o=t.setPointerCapture)||o.call(t)},onPointerMove:t=>{if(!s)return;const i=e.clamp(t.x,0,o.width),a=e.clamp(t.y,0,o.height);m={origin:{x:Math.min(s.x,i),y:Math.min(s.y,a)},size:{width:Math.abs(i-s.x),height:Math.abs(a-s.y)}},null==n||n(m)},onPointerUp:(e,t)=>{var o;m&&(Math.max(m.size.width,m.size.height)*i>a?null==r||r(m):null==l||l()),s=null,m=null,null==n||n(null),null==(o=t.releasePointerCapture)||o.call(t)},onPointerCancel:(e,t)=>{var o;s=null,m=null,null==n||n(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),null==(i=(o=t.callback).onCommit)||i.call(o,e)},onSmallDrag:()=>{var e,o;this.zoomIn(),null==(o=(e=t.callback).onSmallDrag)||o.call(e)}});return this.interactionManager.registerHandlers({modeId:"marqueeZoom",handlers:a,pageIndex:t.pageIndex})}};m.id="zoom";let c=m;const h={manifest:n,create:(e,t)=>new c(a,e,t),reducer:(e=s,t)=>{switch(t.type){case r:return{...e,zoomLevel:t.payload.zoomLevel,currentZoomLevel:t.payload.currentZoomLevel};case l:return{...e,zoomLevel:t.payload.zoomLevel};default:return e}},initialState:s};exports.VerticalZoomFocus=i,exports.ZOOM_PLUGIN_ID=a,exports.ZoomMode=o,exports.ZoomPlugin=c,exports.ZoomPluginPackage=h,exports.initialState=s,exports.manifest=n;
|
|
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 a="zoom",n={id:a,name:"Zoom Plugin",version:"1.0.0",provides:["zoom"],requires:["viewport","scroll"],optional:["interaction-manager"],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="SET_ZOOM_LEVEL",l="SET_INITIAL_ZOOM_LEVEL";const s={zoomLevel:o.Automatic,currentZoomLevel:1};const m=class extends e.BasePlugin{constructor(t,o,a){var n;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 r=o.getPlugin("interaction-manager");var s;this.interactionManager=(null==r?void 0:r.provides())??null,this.minZoom=a.minZoom??.25,this.maxZoom=a.maxZoom??10,this.zoomStep=a.zoomStep??.1,this.presets=a.presets??[],this.zoomRanges=this.normalizeRanges(a.zoomRanges??[]),this.dispatch((s=a.defaultZoomLevel,{type:l,payload:{zoomLevel:s}})),this.viewport.onViewportResize((()=>this.recalcAuto(i.Top)),{mode:"debounce",wait:150}),this.coreStore.onAction(e.SET_ROTATION,(()=>this.recalcAuto(i.Top))),this.coreStore.onAction(e.SET_PAGES,(()=>this.recalcAuto(i.Top))),this.coreStore.onAction(e.SET_DOCUMENT,(()=>this.recalcAuto(i.Top))),null==(n=this.interactionManager)||n.registerMode({id:"marqueeZoom",scope:"page",exclusive:!0,cursor:"zoom-in"}),this.resetReady()}buildCapability(){return{onZoomChange:this.zoom$.on,onStateChange:this.state$.on,zoomIn:()=>this.zoomIn(),zoomOut:()=>this.zoomOut(),zoomToArea:(e,t)=>this.zoomToArea(e,t),requestZoom:(e,t)=>this.handleRequest({level:e,center:t}),requestZoomBy:(e,t)=>{const o=this.state.currentZoomLevel,i=this.toZoom(o+e);return this.handleRequest({level:i,center:t})},enableMarqueeZoom:()=>{var e;null==(e=this.interactionManager)||e.activate("marqueeZoom")},disableMarqueeZoom:()=>{var e;null==(e=this.interactionManager)||e.activateDefaultMode()},toggleMarqueeZoom:()=>{var e,t,o;"marqueeZoom"===(null==(e=this.interactionManager)?void 0:e.getActiveMode())?null==(t=this.interactionManager)||t.activateDefaultMode():null==(o=this.interactionManager)||o.activate("marqueeZoom")},isMarqueeZoomActive:()=>{var e;return"marqueeZoom"===(null==(e=this.interactionManager)?void 0:e.getActiveMode())},registerMarqueeOnPage:e=>this.registerMarqueeOnPage(e),getState:()=>this.state,getPresets:()=>this.presets}}zoomOut(){const e=this.state.currentZoomLevel;return this.handleRequest({level:e,delta:-this.stepFor(e)})}zoomIn(){const e=this.state.currentZoomLevel;return this.handleRequest({level:e,delta:this.stepFor(e)})}zoomToArea(e,t){this.handleZoomToArea(e,t)}async initialize(){this.markReady()}async destroy(){this.zoom$.clear()}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))}handleRequest({level:t,delta:o=0,center:a,focus:n=i.Center,align:l="keep"}){const s=this.viewport.getMetrics(),m=this.state.currentZoomLevel;if(0===s.clientWidth||0===s.clientHeight)return;const c="number"==typeof t?t:this.computeZoomForMode(t,s);if(!1===c)return;const h=e.clamp(c+o,this.minZoom,this.maxZoom),u=Math.floor(100*h)/100,d=a??{vx:s.clientWidth/2,vy:n===i.Top?0:s.clientHeight/2},{desiredScrollLeft:g,desiredScrollTop:p}=this.computeScrollForZoomChange(s,m,u,d,l);isNaN(g)||isNaN(p)||this.viewportPlugin.setViewportScrollMetrics({scrollLeft:g,scrollTop:p}),this.dispatch({type:r,payload:{zoomLevel:"number"==typeof t?u:t,currentZoomLevel:u}}),this.dispatchCoreAction(e.setScale(u)),this.markReady(),this.viewport.scrollTo({x:g,y:p,behavior:"instant"});const v={oldZoom:m,newZoom:u,level:t,center:d,desiredScrollLeft:g,desiredScrollTop:p,viewport:s};this.zoom$.emit(v)}computeZoomForMode(t,i){const a=e.getPagesWithRotatedSize(this.coreState.core);if(!a.length)return!1;const n=this.scroll.getPageGap(),r=this.viewport.getViewportGap();if(0===i.clientWidth||0===i.clientHeight)return!1;const l=i.clientWidth-2*r,s=i.clientHeight-2*r;if(l<=0||s<=0)return!1;let m=0,c=0;switch(a.forEach((e=>{const t=e.reduce(((e,t,o)=>e+t.rotatedSize.width+(o?n:0)),0),o=Math.max(...e.map((e=>e.rotatedSize.height)));m=Math.max(m,t),c=Math.max(c,o)})),t){case o.FitWidth:return l/m;case o.FitPage:return Math.min(l/m,s/c);case o.Automatic:return Math.min(l/m,1);default:return 1}}computeScrollForZoomChange(e,t,o,i,a="keep"){const n=this.scroll.getLayout(),r=this.viewport.getViewportGap(),l=n.totalContentSize.width,s=n.totalContentSize.height,m=e.clientWidth-2*r,c=e.clientHeight-2*r,h=(e,t,o)=>t*o<e?(e-t*o)/2:0,u=h(m,l,t),d=h(c,s,t),g=h(m,l,o),p=h(c,s,o),v=(e.scrollLeft+i.vx-r-u)/t*o+r+g,z=(e.scrollTop+i.vy-r-d)/t*o+r+p,Z="center"===a?v-e.clientWidth/2:v-i.vx,x="center"===a?z-e.clientHeight/2:z-i.vy;return{desiredScrollLeft:Math.max(0,Z),desiredScrollTop:Math.max(0,x)}}handleZoomToArea(e,o){const i=this.coreState.core.rotation,a=this.viewport.getMetrics(),n=this.viewport.getViewportGap(),r=this.state.currentZoomLevel,l=a.clientWidth-2*n,s=a.clientHeight-2*n,m=this.scroll.getLayout(),c=m.virtualItems.find((t=>t.pageLayouts.some((t=>t.pageIndex===e))));if(!c)return;const h=c.pageLayouts.find((t=>t.pageIndex===e)),u=t.rotateRect({width:h.width,height:h.height},o,i),d=this.toZoom(Math.min(l/u.size.width,s/u.size.height)),g=c.x+h.x,p=c.y+h.y,v=g+u.origin.x+u.size.width/2,z=p+u.origin.y+u.size.height/2,Z=(e,t,o)=>t*o<e?(e-t*o)/2:0,x=Z(l,m.totalContentSize.width,r),M=Z(s,m.totalContentSize.height,r),S=n+x+v*r-a.scrollLeft,f=n+M+z*r-a.scrollTop;this.handleRequest({level:d,center:{vx:S,vy:f},align:"center"})}recalcAuto(e){const t=this.state;t.zoomLevel!==o.Automatic&&t.zoomLevel!==o.FitPage&&t.zoomLevel!==o.FitWidth||this.handleRequest({level:t.zoomLevel,focus:e})}onStoreUpdated(e,t){this.state$.emit(t)}registerMarqueeOnPage(t){if(!this.interactionManager)return this.logger.warn("ZoomPlugin","MissingDependency","Interaction manager plugin not loaded, marquee zoom disabled"),()=>{};const o=this.coreState.core.document;if(!o)return this.logger.warn("ZoomPlugin","DocumentNotFound","Document not found"),()=>{};const i=o.pages[t.pageIndex];if(!i)return this.logger.warn("ZoomPlugin","PageNotFound",`Page ${t.pageIndex} not found`),()=>{};const a=function(t){const{pageSize:o,scale:i,minDragPx:a=5,onPreview:n,onCommit:r,onSmallDrag:l}=t;let s=null,m=null;return{onPointerDown:(e,t)=>{var o;s=e,m={origin:{x:e.x,y:e.y},size:{width:0,height:0}},null==n||n(m),null==(o=t.setPointerCapture)||o.call(t)},onPointerMove:t=>{if(!s)return;const i=e.clamp(t.x,0,o.width),a=e.clamp(t.y,0,o.height);m={origin:{x:Math.min(s.x,i),y:Math.min(s.y,a)},size:{width:Math.abs(i-s.x),height:Math.abs(a-s.y)}},null==n||n(m)},onPointerUp:(e,t)=>{var o;m&&(Math.max(m.size.width,m.size.height)*i>a?null==r||r(m):null==l||l()),s=null,m=null,null==n||n(null),null==(o=t.releasePointerCapture)||o.call(t)},onPointerCancel:(e,t)=>{var o;s=null,m=null,null==n||n(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),null==(i=(o=t.callback).onCommit)||i.call(o,e)},onSmallDrag:()=>{var e,o;this.zoomIn(),null==(o=(e=t.callback).onSmallDrag)||o.call(e)}});return this.interactionManager.registerHandlers({modeId:"marqueeZoom",handlers:a,pageIndex:t.pageIndex})}};m.id="zoom";let c=m;const h={manifest:n,create:(e,t)=>new c(a,e,t),reducer:(e=s,t)=>{switch(t.type){case r:return{...e,zoomLevel:t.payload.zoomLevel,currentZoomLevel:t.payload.currentZoomLevel};case l:return{...e,zoomLevel:t.payload.zoomLevel};default:return e}},initialState:s};exports.VerticalZoomFocus=i,exports.ZOOM_PLUGIN_ID=a,exports.ZoomMode=o,exports.ZoomPlugin=c,exports.ZoomPluginPackage=h,exports.initialState=s,exports.manifest=n;
|
|
2
2
|
//# sourceMappingURL=index.cjs.map
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.cjs","sources":["../src/lib/types.ts","../src/lib/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 /** old and new *actual* scale factors */\n oldZoom: number;\n newZoom: number;\n\n /** level used to obtain the newZoom (number | mode) */\n level: ZoomLevel;\n\n /** viewport point kept under the finger / mouse‑wheel focus */\n center: Point;\n\n /** where the viewport should scroll to after the scale change */\n desiredScrollLeft: number;\n desiredScrollTop: number;\n\n /** metrics at the moment the zoom was requested */\n viewport: ViewportMetrics;\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 pageIndex: number;\n scale: number;\n callback: MarqueeZoomCallback;\n}\n\nexport interface ZoomCapability {\n /** subscribe – returns the unsubscribe function */\n onZoomChange: EventHook<ZoomChangeEvent>;\n /** subscribe – returns the unsubscribe function */\n onStateChange: EventHook<ZoomState>;\n\n /** absolute requests -------------------------------------------------- */\n requestZoom(level: ZoomLevel, center?: Point): void;\n /** relative requests -------------------------------------------------- */\n requestZoomBy(delta: number, center?: Point): void;\n\n /** absolute requests -------------------------------------------------- */\n zoomIn(): void;\n zoomOut(): void;\n\n zoomToArea(pageIndex: number, rect: Rect): void;\n\n /** zoom in on an area -------------------------------------------------- */\n enableMarqueeZoom(): void;\n disableMarqueeZoom(): void;\n toggleMarqueeZoom(): void;\n isMarqueeZoomActive(): boolean;\n\n /** register a marquee handler on a page -------------------------------- */\n registerMarqueeOnPage: (opts: RegisterMarqueeOnPageOptions) => () => void;\n\n getState(): ZoomState;\n getPresets(): ZoomPreset[];\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[]; // Define different step sizes for different zoom ranges\n presets?: ZoomPreset[]; // Preset zoom options for dropdown\n}\n\nexport interface ZoomState {\n zoomLevel: ZoomLevel; // last **requested** level\n currentZoomLevel: number; // actual numeric factor\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 /** Scroll so that the focal point ends up …\n * ▸ `\"keep\"` (default) at the same viewport coords\n * ▸ `\"center\"` centred in the viewport */\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'],\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';\n\nimport { ZoomLevel } from './types';\n\n// Action Types\nexport const SET_ZOOM_LEVEL = 'SET_ZOOM_LEVEL';\nexport const SET_INITIAL_ZOOM_LEVEL = 'SET_INITIAL_ZOOM_LEVEL';\n\n// Action Interfaces\nexport interface SetZoomLevelAction extends Action {\n type: typeof SET_ZOOM_LEVEL;\n payload: {\n zoomLevel: ZoomLevel;\n currentZoomLevel: number;\n };\n}\n\nexport interface SetInitialZoomLevelAction extends Action {\n type: typeof SET_INITIAL_ZOOM_LEVEL;\n payload: {\n zoomLevel: ZoomLevel;\n };\n}\n\n// Union Type for All Actions\nexport type ZoomAction = SetZoomLevelAction | SetInitialZoomLevelAction;\n\n// Action Creators\nexport function setZoomLevel(zoomLevel: ZoomLevel, currentZoomLevel: number): SetZoomLevelAction {\n return {\n type: SET_ZOOM_LEVEL,\n payload: { zoomLevel, currentZoomLevel },\n };\n}\n\nexport function setInitialZoomLevel(zoomLevel: ZoomLevel): SetInitialZoomLevelAction {\n return {\n type: SET_INITIAL_ZOOM_LEVEL,\n payload: { zoomLevel },\n };\n}\n","import { Reducer } from '@embedpdf/core';\n\nimport { SET_INITIAL_ZOOM_LEVEL, SET_ZOOM_LEVEL, ZoomAction } from './actions';\nimport { ZoomState, ZoomMode } from './types';\n\nexport const initialState: ZoomState = {\n zoomLevel: ZoomMode.Automatic,\n currentZoomLevel: 1,\n};\n\nexport const zoomReducer: Reducer<ZoomState, ZoomAction> = (state = initialState, action) => {\n switch (action.type) {\n case SET_ZOOM_LEVEL:\n return {\n ...state,\n zoomLevel: action.payload.zoomLevel,\n currentZoomLevel: action.payload.currentZoomLevel,\n };\n case SET_INITIAL_ZOOM_LEVEL:\n return {\n ...state,\n zoomLevel: action.payload.zoomLevel,\n };\n default:\n return state;\n }\n};\n","import {\n BasePlugin,\n PluginRegistry,\n createEmitter,\n clamp,\n setScale,\n SET_PAGES,\n SET_DOCUMENT,\n getPagesWithRotatedSize,\n SET_ROTATION,\n createBehaviorEmitter,\n} from '@embedpdf/core';\nimport { ScrollPlugin, ScrollCapability } from '@embedpdf/plugin-scroll';\nimport { ViewportPlugin, ViewportCapability, ViewportMetrics } from '@embedpdf/plugin-viewport';\n\nimport { setInitialZoomLevel, setZoomLevel, ZoomAction } 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} from './types';\nimport {\n InteractionManagerCapability,\n InteractionManagerPlugin,\n} from '@embedpdf/plugin-interaction-manager';\nimport { Rect, rotateRect } from '@embedpdf/models';\nimport { createMarqueeHandler } from './handlers';\n\nexport class ZoomPlugin extends BasePlugin<\n ZoomPluginConfig,\n ZoomCapability,\n ZoomState,\n ZoomAction\n> {\n static readonly id = 'zoom' as const;\n /* ------------------------------------------------------------------ */\n /* internals */\n /* ------------------------------------------------------------------ */\n private readonly zoom$ = createEmitter<ZoomChangeEvent>();\n private readonly state$ = createBehaviorEmitter<ZoomState>();\n private readonly viewport: ViewportCapability;\n private readonly viewportPlugin: ViewportPlugin;\n private readonly scroll: ScrollCapability;\n private readonly interactionManager: InteractionManagerCapability | null;\n private readonly presets: ZoomPreset[];\n private readonly zoomRanges: ZoomRangeStep[];\n\n private readonly minZoom: number;\n private readonly maxZoom: number;\n private readonly zoomStep: number;\n\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 this.minZoom = cfg.minZoom ?? 0.25;\n this.maxZoom = cfg.maxZoom ?? 10;\n this.zoomStep = cfg.zoomStep ?? 0.1;\n this.presets = cfg.presets ?? [];\n this.zoomRanges = this.normalizeRanges(cfg.zoomRanges ?? []);\n this.dispatch(setInitialZoomLevel(cfg.defaultZoomLevel));\n /* keep \"automatic\" modes up to date -------------------------------- */\n this.viewport.onViewportResize(() => this.recalcAuto(VerticalZoomFocus.Top), {\n mode: 'debounce',\n wait: 150,\n });\n this.coreStore.onAction(SET_ROTATION, () => this.recalcAuto(VerticalZoomFocus.Top));\n this.coreStore.onAction(SET_PAGES, () => this.recalcAuto(VerticalZoomFocus.Top));\n this.coreStore.onAction(SET_DOCUMENT, () => this.recalcAuto(VerticalZoomFocus.Top));\n this.interactionManager?.registerMode({\n id: 'marqueeZoom',\n scope: 'page',\n exclusive: true,\n cursor: 'zoom-in',\n });\n this.resetReady();\n }\n\n /* ------------------------------------------------------------------ */\n /* capability */\n /* ------------------------------------------------------------------ */\n protected buildCapability(): ZoomCapability {\n return {\n onZoomChange: this.zoom$.on,\n onStateChange: this.state$.on,\n zoomIn: () => this.zoomIn(),\n zoomOut: () => this.zoomOut(),\n zoomToArea: (pageIndex, rect) => this.zoomToArea(pageIndex, rect),\n requestZoom: (level, c) => this.handleRequest({ level, center: c }),\n requestZoomBy: (d, c) => {\n const cur = this.state.currentZoomLevel;\n const target = this.toZoom(cur + d);\n return this.handleRequest({ level: target, center: c });\n },\n enableMarqueeZoom: () => {\n this.interactionManager?.activate('marqueeZoom');\n },\n disableMarqueeZoom: () => {\n this.interactionManager?.activateDefaultMode();\n },\n toggleMarqueeZoom: () => {\n if (this.interactionManager?.getActiveMode() === 'marqueeZoom') {\n this.interactionManager?.activateDefaultMode();\n } else {\n this.interactionManager?.activate('marqueeZoom');\n }\n },\n isMarqueeZoomActive: () => this.interactionManager?.getActiveMode() === 'marqueeZoom',\n registerMarqueeOnPage: (opts) => this.registerMarqueeOnPage(opts),\n getState: () => this.state,\n getPresets: () => this.presets,\n };\n }\n\n private zoomOut() {\n const cur = this.state.currentZoomLevel;\n return this.handleRequest({ level: cur, delta: -this.stepFor(cur) });\n }\n\n private zoomIn() {\n const cur = this.state.currentZoomLevel;\n return this.handleRequest({ level: cur, delta: this.stepFor(cur) });\n }\n\n private zoomToArea(pageIndex: number, rect: Rect) {\n this.handleZoomToArea(pageIndex, rect);\n }\n\n /* ------------------------------------------------------------------ */\n /* plugin life‑cycle */\n /* ------------------------------------------------------------------ */\n async initialize(): Promise<void> {\n /* apply the initial zoom */\n }\n\n async destroy() {\n this.zoom$.clear();\n }\n\n /**\n * Sort ranges once, make sure they are sane\n */\n private normalizeRanges(ranges: ZoomRangeStep[]): ZoomRangeStep[] {\n return [...ranges]\n .filter((r) => r.step > 0 && r.max > r.min) // basic sanity\n .sort((a, b) => a.min - b.min);\n }\n\n /** pick the step that applies to a given numeric zoom */\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; // fallback\n }\n\n /** clamp + round helper reused later */\n private toZoom(v: number) {\n return parseFloat(clamp(v, this.minZoom, this.maxZoom).toFixed(2));\n }\n\n /* ------------------------------------------------------------------ */\n /* main entry – handles **every** zoom request */\n /* ------------------------------------------------------------------ */\n private handleRequest({\n level,\n delta = 0,\n center,\n focus = VerticalZoomFocus.Center,\n align = 'keep',\n }: ZoomRequest) {\n const metrics = this.viewport.getMetrics();\n const oldZoom = this.state.currentZoomLevel;\n\n if (metrics.clientWidth === 0 || metrics.clientHeight === 0) {\n return;\n }\n\n /* ------------------------------------------------------------------ */\n /* step 1 – resolve the **target numeric zoom** */\n /* ------------------------------------------------------------------ */\n const base = typeof level === 'number' ? level : this.computeZoomForMode(level, metrics);\n\n if (base === false) {\n return;\n }\n const exactZoom = clamp(base + delta, this.minZoom, this.maxZoom);\n const newZoom = Math.floor(exactZoom * 100) / 100;\n\n /* ------------------------------------------------------------------ */\n /* step 2 – figure out the viewport point we should keep under focus */\n /* ------------------------------------------------------------------ */\n const focusPoint: Point = center ?? {\n vx: metrics.clientWidth / 2,\n vy: focus === VerticalZoomFocus.Top ? 0 : metrics.clientHeight / 2,\n };\n\n /* ------------------------------------------------------------------ */\n /* step 3 – translate that into desired scroll offsets */\n /* ------------------------------------------------------------------ */\n const { desiredScrollLeft, desiredScrollTop } = this.computeScrollForZoomChange(\n metrics,\n oldZoom,\n newZoom,\n focusPoint,\n align,\n );\n\n /* ------------------------------------------------------------------ */\n /* step 4 – dispatch + notify */\n /* ------------------------------------------------------------------ */\n\n if (!isNaN(desiredScrollLeft) && !isNaN(desiredScrollTop)) {\n this.viewportPlugin.setViewportScrollMetrics({\n scrollLeft: desiredScrollLeft,\n scrollTop: desiredScrollTop,\n });\n }\n\n this.dispatch(setZoomLevel(typeof level === 'number' ? newZoom : level, newZoom));\n this.dispatchCoreAction(setScale(newZoom));\n this.markReady();\n\n this.viewport.scrollTo({\n x: desiredScrollLeft,\n y: desiredScrollTop,\n behavior: 'instant',\n });\n\n const evt: ZoomChangeEvent = {\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 /* ------------------------------------------------------------------ */\n /* helpers */\n /* ------------------------------------------------------------------ */\n\n /** numeric zoom for Automatic / FitPage / FitWidth */\n private computeZoomForMode(mode: ZoomMode, vp: ViewportMetrics): number | false {\n const spreads = getPagesWithRotatedSize(this.coreState.core);\n if (!spreads.length) return false;\n\n const pgGap = this.scroll.getPageGap();\n const vpGap = this.viewport.getViewportGap();\n\n if (vp.clientWidth === 0 || vp.clientHeight === 0) {\n return false;\n }\n\n // Available space after accounting for fixed viewport gaps\n const availableWidth = vp.clientWidth - 2 * vpGap;\n const availableHeight = vp.clientHeight - 2 * vpGap;\n\n if (availableWidth <= 0 || availableHeight <= 0) {\n return false;\n }\n\n let maxContentW = 0,\n maxContentH = 0;\n\n spreads.forEach((spread) => {\n // Only include scalable content (pages + page gaps), not viewport gaps\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 /* istanbul ignore next */\n default:\n return 1;\n }\n }\n\n /** where to scroll so that *focus* stays stable after scaling */\n private computeScrollForZoomChange(\n vp: ViewportMetrics,\n oldZoom: number,\n newZoom: number,\n focus: Point,\n align: 'keep' | 'center' = 'keep',\n ) {\n /* unscaled content size ------------------------------------------- */\n const layout = this.scroll.getLayout();\n const vpGap = this.viewport.getViewportGap();\n\n const contentW = layout.totalContentSize.width;\n const contentH = layout.totalContentSize.height;\n\n // Available space for content (excluding fixed viewport gaps)\n const availableWidth = vp.clientWidth - 2 * vpGap;\n const availableHeight = vp.clientHeight - 2 * vpGap;\n\n /* helper: offset if content is narrower than available space ------- */\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 /* content coords of the focal point -------------------------------- */\n // Adjust focus point to account for vpGap and centering offset\n const cx = (vp.scrollLeft + focus.vx - vpGap - offXold) / oldZoom;\n const cy = (vp.scrollTop + focus.vy - vpGap - offYold) / oldZoom;\n\n /* new scroll so that (cx,cy) appears under focus again ------------- */\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(pageIndex: number, rect: Rect) {\n /* -------------------------------------------------- */\n /* 0 – rotation that applies to this page */\n /* -------------------------------------------------- */\n const rotation = this.coreState.core.rotation;\n\n /* -------------------------------------------------- */\n /* viewport + layout basics */\n /* -------------------------------------------------- */\n const vp = this.viewport.getMetrics();\n const vpGap = this.viewport.getViewportGap();\n const oldZ = this.state.currentZoomLevel;\n\n const availableW = vp.clientWidth - 2 * vpGap;\n const availableH = vp.clientHeight - 2 * vpGap;\n\n const layout = this.scroll.getLayout();\n\n /* which virtual item holds the page? */\n const vItem = layout.virtualItems.find((it) =>\n it.pageLayouts.some((p) => p.pageIndex === pageIndex),\n );\n if (!vItem) return;\n\n /* the page layout inside that virtual item */\n const pageRel = vItem.pageLayouts.find((p) => p.pageIndex === pageIndex)!;\n\n /* -------------------------------------------------- */\n /* 1 – rect → rotated‑page space */\n /* -------------------------------------------------- */\n const rotatedRect = rotateRect(\n {\n width: pageRel.width,\n height: pageRel.height,\n },\n rect,\n rotation,\n );\n\n /* -------------------------------------------------- */\n /* 2 – numeric zoom so the rect fits */\n /* -------------------------------------------------- */\n const targetZoom = this.toZoom(\n Math.min(availableW / rotatedRect.size.width, availableH / rotatedRect.size.height),\n );\n\n /* -------------------------------------------------- */\n /* 3 – centre of that rect in *content* coordinates */\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 /* -------------------------------------------------- */\n /* 4 – centre in *viewport* coords before zoom */\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 /* -------------------------------------------------- */\n /* 5 – hand off to the generic zoom handler */\n /* -------------------------------------------------- */\n this.handleRequest({\n level: targetZoom,\n center: { vx: centerVX, vy: centerVY },\n align: 'center',\n });\n }\n\n /** recalculates Automatic / Fit* when viewport or pages change */\n private recalcAuto(focus?: VerticalZoomFocus) {\n const s = this.state;\n if (\n s.zoomLevel === ZoomMode.Automatic ||\n s.zoomLevel === ZoomMode.FitPage ||\n s.zoomLevel === ZoomMode.FitWidth\n )\n this.handleRequest({ level: s.zoomLevel, focus });\n }\n\n override onStoreUpdated(_prevState: ZoomState, newState: ZoomState): void {\n this.state$.emit(newState);\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 document = this.coreState.core.document;\n if (!document) {\n this.logger.warn('ZoomPlugin', 'DocumentNotFound', 'Document not found');\n return () => {};\n }\n\n const page = 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 // Large drag → zoom to the selected area\n this.zoomToArea(opts.pageIndex, rect);\n opts.callback.onCommit?.(rect);\n },\n onSmallDrag: () => {\n // Small drag → simple zoom in\n this.zoomIn();\n opts.callback.onSmallDrag?.();\n },\n });\n\n const off = this.interactionManager.registerHandlers({\n modeId: 'marqueeZoom',\n handlers,\n pageIndex: opts.pageIndex,\n });\n\n return off;\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 } 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 };\n"],"names":["ZoomMode","VerticalZoomFocus","VerticalZoomFocus2","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","SET_ZOOM_LEVEL","SET_INITIAL_ZOOM_LEVEL","initialState","zoomLevel","currentZoomLevel","_ZoomPlugin","BasePlugin","constructor","registry","cfg","super","this","zoom$","createEmitter","state$","createBehaviorEmitter","viewportPlugin","getPlugin","viewport","scroll","interactionManager","normalizeRanges","dispatch","type","payload","onViewportResize","recalcAuto","Top","mode","wait","coreStore","onAction","SET_ROTATION","SET_PAGES","SET_DOCUMENT","_a","registerMode","scope","exclusive","cursor","resetReady","buildCapability","onZoomChange","on","onStateChange","zoomIn","zoomOut","zoomToArea","pageIndex","rect","requestZoom","level","c","handleRequest","center","requestZoomBy","d","cur","state","target","toZoom","enableMarqueeZoom","activate","disableMarqueeZoom","activateDefaultMode","toggleMarqueeZoom","getActiveMode","_b","_c","isMarqueeZoomActive","registerMarqueeOnPage","opts","getState","getPresets","delta","stepFor","handleZoomToArea","initialize","destroy","clear","ranges","filter","r","sort","a","b","zoom","find","v","parseFloat","clamp","toFixed","focus","Center","align","metrics","getMetrics","oldZoom","clientWidth","clientHeight","base","computeZoomForMode","exactZoom","newZoom","Math","floor","focusPoint","vx","vy","desiredScrollLeft","desiredScrollTop","computeScrollForZoomChange","isNaN","setViewportScrollMetrics","scrollLeft","scrollTop","dispatchCoreAction","setScale","markReady","scrollTo","x","y","behavior","evt","emit","vp","spreads","getPagesWithRotatedSize","coreState","core","length","pgGap","getPageGap","vpGap","getViewportGap","availableWidth","availableHeight","maxContentW","maxContentH","forEach","spread","contentW","reduce","s","p","i","rotatedSize","width","contentH","map","height","layout","getLayout","totalContentSize","off","availableSpace","cw","offXold","offYold","offXnew","offYnew","baseLeft","baseTop","rotation","oldZ","availableW","availableH","vItem","virtualItems","it","pageLayouts","some","pageRel","rotatedRect","rotateRect","targetZoom","size","pageAbsX","pageAbsY","cxContent","origin","cyContent","avail","z","centerVX","centerVY","onStoreUpdated","_prevState","newState","logger","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","ZoomPlugin","ZoomPluginPackage","create","config","reducer","action"],"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 /** old and new *actual* scale factors */\n oldZoom: number;\n newZoom: number;\n\n /** level used to obtain the newZoom (number | mode) */\n level: ZoomLevel;\n\n /** viewport point kept under the finger / mouse‑wheel focus */\n center: Point;\n\n /** where the viewport should scroll to after the scale change */\n desiredScrollLeft: number;\n desiredScrollTop: number;\n\n /** metrics at the moment the zoom was requested */\n viewport: ViewportMetrics;\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 pageIndex: number;\n scale: number;\n callback: MarqueeZoomCallback;\n}\n\nexport interface ZoomCapability {\n /** subscribe – returns the unsubscribe function */\n onZoomChange: EventHook<ZoomChangeEvent>;\n /** subscribe – returns the unsubscribe function */\n onStateChange: EventHook<ZoomState>;\n\n /** absolute requests -------------------------------------------------- */\n requestZoom(level: ZoomLevel, center?: Point): void;\n /** relative requests -------------------------------------------------- */\n requestZoomBy(delta: number, center?: Point): void;\n\n /** absolute requests -------------------------------------------------- */\n zoomIn(): void;\n zoomOut(): void;\n\n zoomToArea(pageIndex: number, rect: Rect): void;\n\n /** zoom in on an area -------------------------------------------------- */\n enableMarqueeZoom(): void;\n disableMarqueeZoom(): void;\n toggleMarqueeZoom(): void;\n isMarqueeZoomActive(): boolean;\n\n /** register a marquee handler on a page -------------------------------- */\n registerMarqueeOnPage: (opts: RegisterMarqueeOnPageOptions) => () => void;\n\n getState(): ZoomState;\n getPresets(): ZoomPreset[];\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[]; // Define different step sizes for different zoom ranges\n presets?: ZoomPreset[]; // Preset zoom options for dropdown\n}\n\nexport interface ZoomState {\n zoomLevel: ZoomLevel; // last **requested** level\n currentZoomLevel: number; // actual numeric factor\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 /** Scroll so that the focal point ends up …\n * ▸ `\"keep\"` (default) at the same viewport coords\n * ▸ `\"center\"` centred in the viewport */\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'],\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';\n\nimport { ZoomLevel } from './types';\n\n// Action Types\nexport const SET_ZOOM_LEVEL = 'SET_ZOOM_LEVEL';\nexport const SET_INITIAL_ZOOM_LEVEL = 'SET_INITIAL_ZOOM_LEVEL';\n\n// Action Interfaces\nexport interface SetZoomLevelAction extends Action {\n type: typeof SET_ZOOM_LEVEL;\n payload: {\n zoomLevel: ZoomLevel;\n currentZoomLevel: number;\n };\n}\n\nexport interface SetInitialZoomLevelAction extends Action {\n type: typeof SET_INITIAL_ZOOM_LEVEL;\n payload: {\n zoomLevel: ZoomLevel;\n };\n}\n\n// Union Type for All Actions\nexport type ZoomAction = SetZoomLevelAction | SetInitialZoomLevelAction;\n\n// Action Creators\nexport function setZoomLevel(zoomLevel: ZoomLevel, currentZoomLevel: number): SetZoomLevelAction {\n return {\n type: SET_ZOOM_LEVEL,\n payload: { zoomLevel, currentZoomLevel },\n };\n}\n\nexport function setInitialZoomLevel(zoomLevel: ZoomLevel): SetInitialZoomLevelAction {\n return {\n type: SET_INITIAL_ZOOM_LEVEL,\n payload: { zoomLevel },\n };\n}\n","import { Reducer } from '@embedpdf/core';\n\nimport { SET_INITIAL_ZOOM_LEVEL, SET_ZOOM_LEVEL, ZoomAction } from './actions';\nimport { ZoomState, ZoomMode } from './types';\n\nexport const initialState: ZoomState = {\n zoomLevel: ZoomMode.Automatic,\n currentZoomLevel: 1,\n};\n\nexport const zoomReducer: Reducer<ZoomState, ZoomAction> = (state = initialState, action) => {\n switch (action.type) {\n case SET_ZOOM_LEVEL:\n return {\n ...state,\n zoomLevel: action.payload.zoomLevel,\n currentZoomLevel: action.payload.currentZoomLevel,\n };\n case SET_INITIAL_ZOOM_LEVEL:\n return {\n ...state,\n zoomLevel: action.payload.zoomLevel,\n };\n default:\n return state;\n }\n};\n","import {\n BasePlugin,\n PluginRegistry,\n createEmitter,\n clamp,\n setScale,\n SET_PAGES,\n SET_DOCUMENT,\n getPagesWithRotatedSize,\n SET_ROTATION,\n createBehaviorEmitter,\n} from '@embedpdf/core';\nimport { ScrollPlugin, ScrollCapability } from '@embedpdf/plugin-scroll';\nimport { ViewportPlugin, ViewportCapability, ViewportMetrics } from '@embedpdf/plugin-viewport';\n\nimport { setInitialZoomLevel, setZoomLevel, ZoomAction } 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} from './types';\nimport {\n InteractionManagerCapability,\n InteractionManagerPlugin,\n} from '@embedpdf/plugin-interaction-manager';\nimport { Rect, rotateRect } from '@embedpdf/models';\nimport { createMarqueeHandler } from './handlers';\n\nexport class ZoomPlugin extends BasePlugin<\n ZoomPluginConfig,\n ZoomCapability,\n ZoomState,\n ZoomAction\n> {\n static readonly id = 'zoom' as const;\n /* ------------------------------------------------------------------ */\n /* internals */\n /* ------------------------------------------------------------------ */\n private readonly zoom$ = createEmitter<ZoomChangeEvent>();\n private readonly state$ = createBehaviorEmitter<ZoomState>();\n private readonly viewport: ViewportCapability;\n private readonly viewportPlugin: ViewportPlugin;\n private readonly scroll: ScrollCapability;\n private readonly interactionManager: InteractionManagerCapability | null;\n private readonly presets: ZoomPreset[];\n private readonly zoomRanges: ZoomRangeStep[];\n\n private readonly minZoom: number;\n private readonly maxZoom: number;\n private readonly zoomStep: number;\n\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 this.minZoom = cfg.minZoom ?? 0.25;\n this.maxZoom = cfg.maxZoom ?? 10;\n this.zoomStep = cfg.zoomStep ?? 0.1;\n this.presets = cfg.presets ?? [];\n this.zoomRanges = this.normalizeRanges(cfg.zoomRanges ?? []);\n this.dispatch(setInitialZoomLevel(cfg.defaultZoomLevel));\n /* keep \"automatic\" modes up to date -------------------------------- */\n this.viewport.onViewportResize(() => this.recalcAuto(VerticalZoomFocus.Top), {\n mode: 'debounce',\n wait: 150,\n });\n this.coreStore.onAction(SET_ROTATION, () => this.recalcAuto(VerticalZoomFocus.Top));\n this.coreStore.onAction(SET_PAGES, () => this.recalcAuto(VerticalZoomFocus.Top));\n this.coreStore.onAction(SET_DOCUMENT, () => this.recalcAuto(VerticalZoomFocus.Top));\n this.interactionManager?.registerMode({\n id: 'marqueeZoom',\n scope: 'page',\n exclusive: true,\n cursor: 'zoom-in',\n });\n this.resetReady();\n }\n\n /* ------------------------------------------------------------------ */\n /* capability */\n /* ------------------------------------------------------------------ */\n protected buildCapability(): ZoomCapability {\n return {\n onZoomChange: this.zoom$.on,\n onStateChange: this.state$.on,\n zoomIn: () => this.zoomIn(),\n zoomOut: () => this.zoomOut(),\n zoomToArea: (pageIndex, rect) => this.zoomToArea(pageIndex, rect),\n requestZoom: (level, c) => this.handleRequest({ level, center: c }),\n requestZoomBy: (d, c) => {\n const cur = this.state.currentZoomLevel;\n const target = this.toZoom(cur + d);\n return this.handleRequest({ level: target, center: c });\n },\n enableMarqueeZoom: () => {\n this.interactionManager?.activate('marqueeZoom');\n },\n disableMarqueeZoom: () => {\n this.interactionManager?.activateDefaultMode();\n },\n toggleMarqueeZoom: () => {\n if (this.interactionManager?.getActiveMode() === 'marqueeZoom') {\n this.interactionManager?.activateDefaultMode();\n } else {\n this.interactionManager?.activate('marqueeZoom');\n }\n },\n isMarqueeZoomActive: () => this.interactionManager?.getActiveMode() === 'marqueeZoom',\n registerMarqueeOnPage: (opts) => this.registerMarqueeOnPage(opts),\n getState: () => this.state,\n getPresets: () => this.presets,\n };\n }\n\n private zoomOut() {\n const cur = this.state.currentZoomLevel;\n return this.handleRequest({ level: cur, delta: -this.stepFor(cur) });\n }\n\n private zoomIn() {\n const cur = this.state.currentZoomLevel;\n return this.handleRequest({ level: cur, delta: this.stepFor(cur) });\n }\n\n private zoomToArea(pageIndex: number, rect: Rect) {\n this.handleZoomToArea(pageIndex, rect);\n }\n\n /* ------------------------------------------------------------------ */\n /* plugin life‑cycle */\n /* ------------------------------------------------------------------ */\n async initialize(): Promise<void> {\n /* apply the initial zoom\n /* Mark plugin as ready - zoom will be calculated when viewport has dimensions */\n this.markReady();\n }\n\n async destroy() {\n this.zoom$.clear();\n }\n\n /**\n * Sort ranges once, make sure they are sane\n */\n private normalizeRanges(ranges: ZoomRangeStep[]): ZoomRangeStep[] {\n return [...ranges]\n .filter((r) => r.step > 0 && r.max > r.min) // basic sanity\n .sort((a, b) => a.min - b.min);\n }\n\n /** pick the step that applies to a given numeric zoom */\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; // fallback\n }\n\n /** clamp + round helper reused later */\n private toZoom(v: number) {\n return parseFloat(clamp(v, this.minZoom, this.maxZoom).toFixed(2));\n }\n\n /* ------------------------------------------------------------------ */\n /* main entry – handles **every** zoom request */\n /* ------------------------------------------------------------------ */\n private handleRequest({\n level,\n delta = 0,\n center,\n focus = VerticalZoomFocus.Center,\n align = 'keep',\n }: ZoomRequest) {\n const metrics = this.viewport.getMetrics();\n const oldZoom = this.state.currentZoomLevel;\n\n if (metrics.clientWidth === 0 || metrics.clientHeight === 0) {\n return;\n }\n\n /* ------------------------------------------------------------------ */\n /* step 1 – resolve the **target numeric zoom** */\n /* ------------------------------------------------------------------ */\n const base = typeof level === 'number' ? level : this.computeZoomForMode(level, metrics);\n\n if (base === false) {\n return;\n }\n const exactZoom = clamp(base + delta, this.minZoom, this.maxZoom);\n const newZoom = Math.floor(exactZoom * 100) / 100;\n\n /* ------------------------------------------------------------------ */\n /* step 2 – figure out the viewport point we should keep under focus */\n /* ------------------------------------------------------------------ */\n const focusPoint: Point = center ?? {\n vx: metrics.clientWidth / 2,\n vy: focus === VerticalZoomFocus.Top ? 0 : metrics.clientHeight / 2,\n };\n\n /* ------------------------------------------------------------------ */\n /* step 3 – translate that into desired scroll offsets */\n /* ------------------------------------------------------------------ */\n const { desiredScrollLeft, desiredScrollTop } = this.computeScrollForZoomChange(\n metrics,\n oldZoom,\n newZoom,\n focusPoint,\n align,\n );\n\n /* ------------------------------------------------------------------ */\n /* step 4 – dispatch + notify */\n /* ------------------------------------------------------------------ */\n\n if (!isNaN(desiredScrollLeft) && !isNaN(desiredScrollTop)) {\n this.viewportPlugin.setViewportScrollMetrics({\n scrollLeft: desiredScrollLeft,\n scrollTop: desiredScrollTop,\n });\n }\n\n this.dispatch(setZoomLevel(typeof level === 'number' ? newZoom : level, newZoom));\n this.dispatchCoreAction(setScale(newZoom));\n this.markReady();\n\n this.viewport.scrollTo({\n x: desiredScrollLeft,\n y: desiredScrollTop,\n behavior: 'instant',\n });\n\n const evt: ZoomChangeEvent = {\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 /* ------------------------------------------------------------------ */\n /* helpers */\n /* ------------------------------------------------------------------ */\n\n /** numeric zoom for Automatic / FitPage / FitWidth */\n private computeZoomForMode(mode: ZoomMode, vp: ViewportMetrics): number | false {\n const spreads = getPagesWithRotatedSize(this.coreState.core);\n if (!spreads.length) return false;\n\n const pgGap = this.scroll.getPageGap();\n const vpGap = this.viewport.getViewportGap();\n\n if (vp.clientWidth === 0 || vp.clientHeight === 0) {\n return false;\n }\n\n // Available space after accounting for fixed viewport gaps\n const availableWidth = vp.clientWidth - 2 * vpGap;\n const availableHeight = vp.clientHeight - 2 * vpGap;\n\n if (availableWidth <= 0 || availableHeight <= 0) {\n return false;\n }\n\n let maxContentW = 0,\n maxContentH = 0;\n\n spreads.forEach((spread) => {\n // Only include scalable content (pages + page gaps), not viewport gaps\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 /* istanbul ignore next */\n default:\n return 1;\n }\n }\n\n /** where to scroll so that *focus* stays stable after scaling */\n private computeScrollForZoomChange(\n vp: ViewportMetrics,\n oldZoom: number,\n newZoom: number,\n focus: Point,\n align: 'keep' | 'center' = 'keep',\n ) {\n /* unscaled content size ------------------------------------------- */\n const layout = this.scroll.getLayout();\n const vpGap = this.viewport.getViewportGap();\n\n const contentW = layout.totalContentSize.width;\n const contentH = layout.totalContentSize.height;\n\n // Available space for content (excluding fixed viewport gaps)\n const availableWidth = vp.clientWidth - 2 * vpGap;\n const availableHeight = vp.clientHeight - 2 * vpGap;\n\n /* helper: offset if content is narrower than available space ------- */\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 /* content coords of the focal point -------------------------------- */\n // Adjust focus point to account for vpGap and centering offset\n const cx = (vp.scrollLeft + focus.vx - vpGap - offXold) / oldZoom;\n const cy = (vp.scrollTop + focus.vy - vpGap - offYold) / oldZoom;\n\n /* new scroll so that (cx,cy) appears under focus again ------------- */\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(pageIndex: number, rect: Rect) {\n /* -------------------------------------------------- */\n /* 0 – rotation that applies to this page */\n /* -------------------------------------------------- */\n const rotation = this.coreState.core.rotation;\n\n /* -------------------------------------------------- */\n /* viewport + layout basics */\n /* -------------------------------------------------- */\n const vp = this.viewport.getMetrics();\n const vpGap = this.viewport.getViewportGap();\n const oldZ = this.state.currentZoomLevel;\n\n const availableW = vp.clientWidth - 2 * vpGap;\n const availableH = vp.clientHeight - 2 * vpGap;\n\n const layout = this.scroll.getLayout();\n\n /* which virtual item holds the page? */\n const vItem = layout.virtualItems.find((it) =>\n it.pageLayouts.some((p) => p.pageIndex === pageIndex),\n );\n if (!vItem) return;\n\n /* the page layout inside that virtual item */\n const pageRel = vItem.pageLayouts.find((p) => p.pageIndex === pageIndex)!;\n\n /* -------------------------------------------------- */\n /* 1 – rect → rotated‑page space */\n /* -------------------------------------------------- */\n const rotatedRect = rotateRect(\n {\n width: pageRel.width,\n height: pageRel.height,\n },\n rect,\n rotation,\n );\n\n /* -------------------------------------------------- */\n /* 2 – numeric zoom so the rect fits */\n /* -------------------------------------------------- */\n const targetZoom = this.toZoom(\n Math.min(availableW / rotatedRect.size.width, availableH / rotatedRect.size.height),\n );\n\n /* -------------------------------------------------- */\n /* 3 – centre of that rect in *content* coordinates */\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 /* -------------------------------------------------- */\n /* 4 – centre in *viewport* coords before zoom */\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 /* -------------------------------------------------- */\n /* 5 – hand off to the generic zoom handler */\n /* -------------------------------------------------- */\n this.handleRequest({\n level: targetZoom,\n center: { vx: centerVX, vy: centerVY },\n align: 'center',\n });\n }\n\n /** recalculates Automatic / Fit* when viewport or pages change */\n private recalcAuto(focus?: VerticalZoomFocus) {\n const s = this.state;\n if (\n s.zoomLevel === ZoomMode.Automatic ||\n s.zoomLevel === ZoomMode.FitPage ||\n s.zoomLevel === ZoomMode.FitWidth\n )\n this.handleRequest({ level: s.zoomLevel, focus });\n }\n\n override onStoreUpdated(_prevState: ZoomState, newState: ZoomState): void {\n this.state$.emit(newState);\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 document = this.coreState.core.document;\n if (!document) {\n this.logger.warn('ZoomPlugin', 'DocumentNotFound', 'Document not found');\n return () => {};\n }\n\n const page = 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 // Large drag → zoom to the selected area\n this.zoomToArea(opts.pageIndex, rect);\n opts.callback.onCommit?.(rect);\n },\n onSmallDrag: () => {\n // Small drag → simple zoom in\n this.zoomIn();\n opts.callback.onSmallDrag?.();\n },\n });\n\n const off = this.interactionManager.registerHandlers({\n modeId: 'marqueeZoom',\n handlers,\n pageIndex: opts.pageIndex,\n });\n\n return off;\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 } 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 };\n"],"names":["ZoomMode","VerticalZoomFocus","VerticalZoomFocus2","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","SET_ZOOM_LEVEL","SET_INITIAL_ZOOM_LEVEL","initialState","zoomLevel","currentZoomLevel","_ZoomPlugin","BasePlugin","constructor","registry","cfg","super","this","zoom$","createEmitter","state$","createBehaviorEmitter","viewportPlugin","getPlugin","viewport","scroll","interactionManager","normalizeRanges","dispatch","type","payload","onViewportResize","recalcAuto","Top","mode","wait","coreStore","onAction","SET_ROTATION","SET_PAGES","SET_DOCUMENT","_a","registerMode","scope","exclusive","cursor","resetReady","buildCapability","onZoomChange","on","onStateChange","zoomIn","zoomOut","zoomToArea","pageIndex","rect","requestZoom","level","c","handleRequest","center","requestZoomBy","d","cur","state","target","toZoom","enableMarqueeZoom","activate","disableMarqueeZoom","activateDefaultMode","toggleMarqueeZoom","getActiveMode","_b","_c","isMarqueeZoomActive","registerMarqueeOnPage","opts","getState","getPresets","delta","stepFor","handleZoomToArea","initialize","markReady","destroy","clear","ranges","filter","r","sort","a","b","zoom","find","v","parseFloat","clamp","toFixed","focus","Center","align","metrics","getMetrics","oldZoom","clientWidth","clientHeight","base","computeZoomForMode","exactZoom","newZoom","Math","floor","focusPoint","vx","vy","desiredScrollLeft","desiredScrollTop","computeScrollForZoomChange","isNaN","setViewportScrollMetrics","scrollLeft","scrollTop","dispatchCoreAction","setScale","scrollTo","x","y","behavior","evt","emit","vp","spreads","getPagesWithRotatedSize","coreState","core","length","pgGap","getPageGap","vpGap","getViewportGap","availableWidth","availableHeight","maxContentW","maxContentH","forEach","spread","contentW","reduce","s","p","i","rotatedSize","width","contentH","map","height","layout","getLayout","totalContentSize","off","availableSpace","cw","offXold","offYold","offXnew","offYnew","baseLeft","baseTop","rotation","oldZ","availableW","availableH","vItem","virtualItems","it","pageLayouts","some","pageRel","rotatedRect","rotateRect","targetZoom","size","pageAbsX","pageAbsY","cxContent","origin","cyContent","avail","z","centerVX","centerVY","onStoreUpdated","_prevState","newState","logger","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","ZoomPlugin","ZoomPluginPackage","create","config","reducer","action"],"mappings":"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"}
|
package/dist/index.js
CHANGED
|
@@ -289,6 +289,7 @@ const _ZoomPlugin = class _ZoomPlugin extends BasePlugin {
|
|
|
289
289
|
/* plugin life‑cycle */
|
|
290
290
|
/* ------------------------------------------------------------------ */
|
|
291
291
|
async initialize() {
|
|
292
|
+
this.markReady();
|
|
292
293
|
}
|
|
293
294
|
async destroy() {
|
|
294
295
|
this.zoom$.clear();
|
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 /** old and new *actual* scale factors */\n oldZoom: number;\n newZoom: number;\n\n /** level used to obtain the newZoom (number | mode) */\n level: ZoomLevel;\n\n /** viewport point kept under the finger / mouse‑wheel focus */\n center: Point;\n\n /** where the viewport should scroll to after the scale change */\n desiredScrollLeft: number;\n desiredScrollTop: number;\n\n /** metrics at the moment the zoom was requested */\n viewport: ViewportMetrics;\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 pageIndex: number;\n scale: number;\n callback: MarqueeZoomCallback;\n}\n\nexport interface ZoomCapability {\n /** subscribe – returns the unsubscribe function */\n onZoomChange: EventHook<ZoomChangeEvent>;\n /** subscribe – returns the unsubscribe function */\n onStateChange: EventHook<ZoomState>;\n\n /** absolute requests -------------------------------------------------- */\n requestZoom(level: ZoomLevel, center?: Point): void;\n /** relative requests -------------------------------------------------- */\n requestZoomBy(delta: number, center?: Point): void;\n\n /** absolute requests -------------------------------------------------- */\n zoomIn(): void;\n zoomOut(): void;\n\n zoomToArea(pageIndex: number, rect: Rect): void;\n\n /** zoom in on an area -------------------------------------------------- */\n enableMarqueeZoom(): void;\n disableMarqueeZoom(): void;\n toggleMarqueeZoom(): void;\n isMarqueeZoomActive(): boolean;\n\n /** register a marquee handler on a page -------------------------------- */\n registerMarqueeOnPage: (opts: RegisterMarqueeOnPageOptions) => () => void;\n\n getState(): ZoomState;\n getPresets(): ZoomPreset[];\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[]; // Define different step sizes for different zoom ranges\n presets?: ZoomPreset[]; // Preset zoom options for dropdown\n}\n\nexport interface ZoomState {\n zoomLevel: ZoomLevel; // last **requested** level\n currentZoomLevel: number; // actual numeric factor\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 /** Scroll so that the focal point ends up …\n * ▸ `\"keep\"` (default) at the same viewport coords\n * ▸ `\"center\"` centred in the viewport */\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'],\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';\n\nimport { ZoomLevel } from './types';\n\n// Action Types\nexport const SET_ZOOM_LEVEL = 'SET_ZOOM_LEVEL';\nexport const SET_INITIAL_ZOOM_LEVEL = 'SET_INITIAL_ZOOM_LEVEL';\n\n// Action Interfaces\nexport interface SetZoomLevelAction extends Action {\n type: typeof SET_ZOOM_LEVEL;\n payload: {\n zoomLevel: ZoomLevel;\n currentZoomLevel: number;\n };\n}\n\nexport interface SetInitialZoomLevelAction extends Action {\n type: typeof SET_INITIAL_ZOOM_LEVEL;\n payload: {\n zoomLevel: ZoomLevel;\n };\n}\n\n// Union Type for All Actions\nexport type ZoomAction = SetZoomLevelAction | SetInitialZoomLevelAction;\n\n// Action Creators\nexport function setZoomLevel(zoomLevel: ZoomLevel, currentZoomLevel: number): SetZoomLevelAction {\n return {\n type: SET_ZOOM_LEVEL,\n payload: { zoomLevel, currentZoomLevel },\n };\n}\n\nexport function setInitialZoomLevel(zoomLevel: ZoomLevel): SetInitialZoomLevelAction {\n return {\n type: SET_INITIAL_ZOOM_LEVEL,\n payload: { zoomLevel },\n };\n}\n","import { Reducer } from '@embedpdf/core';\n\nimport { SET_INITIAL_ZOOM_LEVEL, SET_ZOOM_LEVEL, ZoomAction } from './actions';\nimport { ZoomState, ZoomMode } from './types';\n\nexport const initialState: ZoomState = {\n zoomLevel: ZoomMode.Automatic,\n currentZoomLevel: 1,\n};\n\nexport const zoomReducer: Reducer<ZoomState, ZoomAction> = (state = initialState, action) => {\n switch (action.type) {\n case SET_ZOOM_LEVEL:\n return {\n ...state,\n zoomLevel: action.payload.zoomLevel,\n currentZoomLevel: action.payload.currentZoomLevel,\n };\n case SET_INITIAL_ZOOM_LEVEL:\n return {\n ...state,\n zoomLevel: action.payload.zoomLevel,\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 SET_PAGES,\n SET_DOCUMENT,\n getPagesWithRotatedSize,\n SET_ROTATION,\n createBehaviorEmitter,\n} from '@embedpdf/core';\nimport { ScrollPlugin, ScrollCapability } from '@embedpdf/plugin-scroll';\nimport { ViewportPlugin, ViewportCapability, ViewportMetrics } from '@embedpdf/plugin-viewport';\n\nimport { setInitialZoomLevel, setZoomLevel, ZoomAction } 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} from './types';\nimport {\n InteractionManagerCapability,\n InteractionManagerPlugin,\n} from '@embedpdf/plugin-interaction-manager';\nimport { Rect, rotateRect } from '@embedpdf/models';\nimport { createMarqueeHandler } from './handlers';\n\nexport class ZoomPlugin extends BasePlugin<\n ZoomPluginConfig,\n ZoomCapability,\n ZoomState,\n ZoomAction\n> {\n static readonly id = 'zoom' as const;\n /* ------------------------------------------------------------------ */\n /* internals */\n /* ------------------------------------------------------------------ */\n private readonly zoom$ = createEmitter<ZoomChangeEvent>();\n private readonly state$ = createBehaviorEmitter<ZoomState>();\n private readonly viewport: ViewportCapability;\n private readonly viewportPlugin: ViewportPlugin;\n private readonly scroll: ScrollCapability;\n private readonly interactionManager: InteractionManagerCapability | null;\n private readonly presets: ZoomPreset[];\n private readonly zoomRanges: ZoomRangeStep[];\n\n private readonly minZoom: number;\n private readonly maxZoom: number;\n private readonly zoomStep: number;\n\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 this.minZoom = cfg.minZoom ?? 0.25;\n this.maxZoom = cfg.maxZoom ?? 10;\n this.zoomStep = cfg.zoomStep ?? 0.1;\n this.presets = cfg.presets ?? [];\n this.zoomRanges = this.normalizeRanges(cfg.zoomRanges ?? []);\n this.dispatch(setInitialZoomLevel(cfg.defaultZoomLevel));\n /* keep \"automatic\" modes up to date -------------------------------- */\n this.viewport.onViewportResize(() => this.recalcAuto(VerticalZoomFocus.Top), {\n mode: 'debounce',\n wait: 150,\n });\n this.coreStore.onAction(SET_ROTATION, () => this.recalcAuto(VerticalZoomFocus.Top));\n this.coreStore.onAction(SET_PAGES, () => this.recalcAuto(VerticalZoomFocus.Top));\n this.coreStore.onAction(SET_DOCUMENT, () => this.recalcAuto(VerticalZoomFocus.Top));\n this.interactionManager?.registerMode({\n id: 'marqueeZoom',\n scope: 'page',\n exclusive: true,\n cursor: 'zoom-in',\n });\n this.resetReady();\n }\n\n /* ------------------------------------------------------------------ */\n /* capability */\n /* ------------------------------------------------------------------ */\n protected buildCapability(): ZoomCapability {\n return {\n onZoomChange: this.zoom$.on,\n onStateChange: this.state$.on,\n zoomIn: () => this.zoomIn(),\n zoomOut: () => this.zoomOut(),\n zoomToArea: (pageIndex, rect) => this.zoomToArea(pageIndex, rect),\n requestZoom: (level, c) => this.handleRequest({ level, center: c }),\n requestZoomBy: (d, c) => {\n const cur = this.state.currentZoomLevel;\n const target = this.toZoom(cur + d);\n return this.handleRequest({ level: target, center: c });\n },\n enableMarqueeZoom: () => {\n this.interactionManager?.activate('marqueeZoom');\n },\n disableMarqueeZoom: () => {\n this.interactionManager?.activateDefaultMode();\n },\n toggleMarqueeZoom: () => {\n if (this.interactionManager?.getActiveMode() === 'marqueeZoom') {\n this.interactionManager?.activateDefaultMode();\n } else {\n this.interactionManager?.activate('marqueeZoom');\n }\n },\n isMarqueeZoomActive: () => this.interactionManager?.getActiveMode() === 'marqueeZoom',\n registerMarqueeOnPage: (opts) => this.registerMarqueeOnPage(opts),\n getState: () => this.state,\n getPresets: () => this.presets,\n };\n }\n\n private zoomOut() {\n const cur = this.state.currentZoomLevel;\n return this.handleRequest({ level: cur, delta: -this.stepFor(cur) });\n }\n\n private zoomIn() {\n const cur = this.state.currentZoomLevel;\n return this.handleRequest({ level: cur, delta: this.stepFor(cur) });\n }\n\n private zoomToArea(pageIndex: number, rect: Rect) {\n this.handleZoomToArea(pageIndex, rect);\n }\n\n /* ------------------------------------------------------------------ */\n /* plugin life‑cycle */\n /* ------------------------------------------------------------------ */\n async initialize(): Promise<void> {\n /* apply the initial zoom */\n }\n\n async destroy() {\n this.zoom$.clear();\n }\n\n /**\n * Sort ranges once, make sure they are sane\n */\n private normalizeRanges(ranges: ZoomRangeStep[]): ZoomRangeStep[] {\n return [...ranges]\n .filter((r) => r.step > 0 && r.max > r.min) // basic sanity\n .sort((a, b) => a.min - b.min);\n }\n\n /** pick the step that applies to a given numeric zoom */\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; // fallback\n }\n\n /** clamp + round helper reused later */\n private toZoom(v: number) {\n return parseFloat(clamp(v, this.minZoom, this.maxZoom).toFixed(2));\n }\n\n /* ------------------------------------------------------------------ */\n /* main entry – handles **every** zoom request */\n /* ------------------------------------------------------------------ */\n private handleRequest({\n level,\n delta = 0,\n center,\n focus = VerticalZoomFocus.Center,\n align = 'keep',\n }: ZoomRequest) {\n const metrics = this.viewport.getMetrics();\n const oldZoom = this.state.currentZoomLevel;\n\n if (metrics.clientWidth === 0 || metrics.clientHeight === 0) {\n return;\n }\n\n /* ------------------------------------------------------------------ */\n /* step 1 – resolve the **target numeric zoom** */\n /* ------------------------------------------------------------------ */\n const base = typeof level === 'number' ? level : this.computeZoomForMode(level, metrics);\n\n if (base === false) {\n return;\n }\n const exactZoom = clamp(base + delta, this.minZoom, this.maxZoom);\n const newZoom = Math.floor(exactZoom * 100) / 100;\n\n /* ------------------------------------------------------------------ */\n /* step 2 – figure out the viewport point we should keep under focus */\n /* ------------------------------------------------------------------ */\n const focusPoint: Point = center ?? {\n vx: metrics.clientWidth / 2,\n vy: focus === VerticalZoomFocus.Top ? 0 : metrics.clientHeight / 2,\n };\n\n /* ------------------------------------------------------------------ */\n /* step 3 – translate that into desired scroll offsets */\n /* ------------------------------------------------------------------ */\n const { desiredScrollLeft, desiredScrollTop } = this.computeScrollForZoomChange(\n metrics,\n oldZoom,\n newZoom,\n focusPoint,\n align,\n );\n\n /* ------------------------------------------------------------------ */\n /* step 4 – dispatch + notify */\n /* ------------------------------------------------------------------ */\n\n if (!isNaN(desiredScrollLeft) && !isNaN(desiredScrollTop)) {\n this.viewportPlugin.setViewportScrollMetrics({\n scrollLeft: desiredScrollLeft,\n scrollTop: desiredScrollTop,\n });\n }\n\n this.dispatch(setZoomLevel(typeof level === 'number' ? newZoom : level, newZoom));\n this.dispatchCoreAction(setScale(newZoom));\n this.markReady();\n\n this.viewport.scrollTo({\n x: desiredScrollLeft,\n y: desiredScrollTop,\n behavior: 'instant',\n });\n\n const evt: ZoomChangeEvent = {\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 /* ------------------------------------------------------------------ */\n /* helpers */\n /* ------------------------------------------------------------------ */\n\n /** numeric zoom for Automatic / FitPage / FitWidth */\n private computeZoomForMode(mode: ZoomMode, vp: ViewportMetrics): number | false {\n const spreads = getPagesWithRotatedSize(this.coreState.core);\n if (!spreads.length) return false;\n\n const pgGap = this.scroll.getPageGap();\n const vpGap = this.viewport.getViewportGap();\n\n if (vp.clientWidth === 0 || vp.clientHeight === 0) {\n return false;\n }\n\n // Available space after accounting for fixed viewport gaps\n const availableWidth = vp.clientWidth - 2 * vpGap;\n const availableHeight = vp.clientHeight - 2 * vpGap;\n\n if (availableWidth <= 0 || availableHeight <= 0) {\n return false;\n }\n\n let maxContentW = 0,\n maxContentH = 0;\n\n spreads.forEach((spread) => {\n // Only include scalable content (pages + page gaps), not viewport gaps\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 /* istanbul ignore next */\n default:\n return 1;\n }\n }\n\n /** where to scroll so that *focus* stays stable after scaling */\n private computeScrollForZoomChange(\n vp: ViewportMetrics,\n oldZoom: number,\n newZoom: number,\n focus: Point,\n align: 'keep' | 'center' = 'keep',\n ) {\n /* unscaled content size ------------------------------------------- */\n const layout = this.scroll.getLayout();\n const vpGap = this.viewport.getViewportGap();\n\n const contentW = layout.totalContentSize.width;\n const contentH = layout.totalContentSize.height;\n\n // Available space for content (excluding fixed viewport gaps)\n const availableWidth = vp.clientWidth - 2 * vpGap;\n const availableHeight = vp.clientHeight - 2 * vpGap;\n\n /* helper: offset if content is narrower than available space ------- */\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 /* content coords of the focal point -------------------------------- */\n // Adjust focus point to account for vpGap and centering offset\n const cx = (vp.scrollLeft + focus.vx - vpGap - offXold) / oldZoom;\n const cy = (vp.scrollTop + focus.vy - vpGap - offYold) / oldZoom;\n\n /* new scroll so that (cx,cy) appears under focus again ------------- */\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(pageIndex: number, rect: Rect) {\n /* -------------------------------------------------- */\n /* 0 – rotation that applies to this page */\n /* -------------------------------------------------- */\n const rotation = this.coreState.core.rotation;\n\n /* -------------------------------------------------- */\n /* viewport + layout basics */\n /* -------------------------------------------------- */\n const vp = this.viewport.getMetrics();\n const vpGap = this.viewport.getViewportGap();\n const oldZ = this.state.currentZoomLevel;\n\n const availableW = vp.clientWidth - 2 * vpGap;\n const availableH = vp.clientHeight - 2 * vpGap;\n\n const layout = this.scroll.getLayout();\n\n /* which virtual item holds the page? */\n const vItem = layout.virtualItems.find((it) =>\n it.pageLayouts.some((p) => p.pageIndex === pageIndex),\n );\n if (!vItem) return;\n\n /* the page layout inside that virtual item */\n const pageRel = vItem.pageLayouts.find((p) => p.pageIndex === pageIndex)!;\n\n /* -------------------------------------------------- */\n /* 1 – rect → rotated‑page space */\n /* -------------------------------------------------- */\n const rotatedRect = rotateRect(\n {\n width: pageRel.width,\n height: pageRel.height,\n },\n rect,\n rotation,\n );\n\n /* -------------------------------------------------- */\n /* 2 – numeric zoom so the rect fits */\n /* -------------------------------------------------- */\n const targetZoom = this.toZoom(\n Math.min(availableW / rotatedRect.size.width, availableH / rotatedRect.size.height),\n );\n\n /* -------------------------------------------------- */\n /* 3 – centre of that rect in *content* coordinates */\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 /* -------------------------------------------------- */\n /* 4 – centre in *viewport* coords before zoom */\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 /* -------------------------------------------------- */\n /* 5 – hand off to the generic zoom handler */\n /* -------------------------------------------------- */\n this.handleRequest({\n level: targetZoom,\n center: { vx: centerVX, vy: centerVY },\n align: 'center',\n });\n }\n\n /** recalculates Automatic / Fit* when viewport or pages change */\n private recalcAuto(focus?: VerticalZoomFocus) {\n const s = this.state;\n if (\n s.zoomLevel === ZoomMode.Automatic ||\n s.zoomLevel === ZoomMode.FitPage ||\n s.zoomLevel === ZoomMode.FitWidth\n )\n this.handleRequest({ level: s.zoomLevel, focus });\n }\n\n override onStoreUpdated(_prevState: ZoomState, newState: ZoomState): void {\n this.state$.emit(newState);\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 document = this.coreState.core.document;\n if (!document) {\n this.logger.warn('ZoomPlugin', 'DocumentNotFound', 'Document not found');\n return () => {};\n }\n\n const page = 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 // Large drag → zoom to the selected area\n this.zoomToArea(opts.pageIndex, rect);\n opts.callback.onCommit?.(rect);\n },\n onSmallDrag: () => {\n // Small drag → simple zoom in\n this.zoomIn();\n opts.callback.onSmallDrag?.();\n },\n });\n\n const off = this.interactionManager.registerHandlers({\n modeId: 'marqueeZoom',\n handlers,\n pageIndex: opts.pageIndex,\n });\n\n return off;\n }\n}\n","import { PluginPackage } from '@embedpdf/core';\n\nimport { ZoomAction } from './actions';\nimport { manifest, ZOOM_PLUGIN_ID } from './manifest';\nimport { zoomReducer, initialState } 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 };\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 /** old and new *actual* scale factors */\n oldZoom: number;\n newZoom: number;\n\n /** level used to obtain the newZoom (number | mode) */\n level: ZoomLevel;\n\n /** viewport point kept under the finger / mouse‑wheel focus */\n center: Point;\n\n /** where the viewport should scroll to after the scale change */\n desiredScrollLeft: number;\n desiredScrollTop: number;\n\n /** metrics at the moment the zoom was requested */\n viewport: ViewportMetrics;\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 pageIndex: number;\n scale: number;\n callback: MarqueeZoomCallback;\n}\n\nexport interface ZoomCapability {\n /** subscribe – returns the unsubscribe function */\n onZoomChange: EventHook<ZoomChangeEvent>;\n /** subscribe – returns the unsubscribe function */\n onStateChange: EventHook<ZoomState>;\n\n /** absolute requests -------------------------------------------------- */\n requestZoom(level: ZoomLevel, center?: Point): void;\n /** relative requests -------------------------------------------------- */\n requestZoomBy(delta: number, center?: Point): void;\n\n /** absolute requests -------------------------------------------------- */\n zoomIn(): void;\n zoomOut(): void;\n\n zoomToArea(pageIndex: number, rect: Rect): void;\n\n /** zoom in on an area -------------------------------------------------- */\n enableMarqueeZoom(): void;\n disableMarqueeZoom(): void;\n toggleMarqueeZoom(): void;\n isMarqueeZoomActive(): boolean;\n\n /** register a marquee handler on a page -------------------------------- */\n registerMarqueeOnPage: (opts: RegisterMarqueeOnPageOptions) => () => void;\n\n getState(): ZoomState;\n getPresets(): ZoomPreset[];\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[]; // Define different step sizes for different zoom ranges\n presets?: ZoomPreset[]; // Preset zoom options for dropdown\n}\n\nexport interface ZoomState {\n zoomLevel: ZoomLevel; // last **requested** level\n currentZoomLevel: number; // actual numeric factor\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 /** Scroll so that the focal point ends up …\n * ▸ `\"keep\"` (default) at the same viewport coords\n * ▸ `\"center\"` centred in the viewport */\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'],\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';\n\nimport { ZoomLevel } from './types';\n\n// Action Types\nexport const SET_ZOOM_LEVEL = 'SET_ZOOM_LEVEL';\nexport const SET_INITIAL_ZOOM_LEVEL = 'SET_INITIAL_ZOOM_LEVEL';\n\n// Action Interfaces\nexport interface SetZoomLevelAction extends Action {\n type: typeof SET_ZOOM_LEVEL;\n payload: {\n zoomLevel: ZoomLevel;\n currentZoomLevel: number;\n };\n}\n\nexport interface SetInitialZoomLevelAction extends Action {\n type: typeof SET_INITIAL_ZOOM_LEVEL;\n payload: {\n zoomLevel: ZoomLevel;\n };\n}\n\n// Union Type for All Actions\nexport type ZoomAction = SetZoomLevelAction | SetInitialZoomLevelAction;\n\n// Action Creators\nexport function setZoomLevel(zoomLevel: ZoomLevel, currentZoomLevel: number): SetZoomLevelAction {\n return {\n type: SET_ZOOM_LEVEL,\n payload: { zoomLevel, currentZoomLevel },\n };\n}\n\nexport function setInitialZoomLevel(zoomLevel: ZoomLevel): SetInitialZoomLevelAction {\n return {\n type: SET_INITIAL_ZOOM_LEVEL,\n payload: { zoomLevel },\n };\n}\n","import { Reducer } from '@embedpdf/core';\n\nimport { SET_INITIAL_ZOOM_LEVEL, SET_ZOOM_LEVEL, ZoomAction } from './actions';\nimport { ZoomState, ZoomMode } from './types';\n\nexport const initialState: ZoomState = {\n zoomLevel: ZoomMode.Automatic,\n currentZoomLevel: 1,\n};\n\nexport const zoomReducer: Reducer<ZoomState, ZoomAction> = (state = initialState, action) => {\n switch (action.type) {\n case SET_ZOOM_LEVEL:\n return {\n ...state,\n zoomLevel: action.payload.zoomLevel,\n currentZoomLevel: action.payload.currentZoomLevel,\n };\n case SET_INITIAL_ZOOM_LEVEL:\n return {\n ...state,\n zoomLevel: action.payload.zoomLevel,\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 SET_PAGES,\n SET_DOCUMENT,\n getPagesWithRotatedSize,\n SET_ROTATION,\n createBehaviorEmitter,\n} from '@embedpdf/core';\nimport { ScrollPlugin, ScrollCapability } from '@embedpdf/plugin-scroll';\nimport { ViewportPlugin, ViewportCapability, ViewportMetrics } from '@embedpdf/plugin-viewport';\n\nimport { setInitialZoomLevel, setZoomLevel, ZoomAction } 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} from './types';\nimport {\n InteractionManagerCapability,\n InteractionManagerPlugin,\n} from '@embedpdf/plugin-interaction-manager';\nimport { Rect, rotateRect } from '@embedpdf/models';\nimport { createMarqueeHandler } from './handlers';\n\nexport class ZoomPlugin extends BasePlugin<\n ZoomPluginConfig,\n ZoomCapability,\n ZoomState,\n ZoomAction\n> {\n static readonly id = 'zoom' as const;\n /* ------------------------------------------------------------------ */\n /* internals */\n /* ------------------------------------------------------------------ */\n private readonly zoom$ = createEmitter<ZoomChangeEvent>();\n private readonly state$ = createBehaviorEmitter<ZoomState>();\n private readonly viewport: ViewportCapability;\n private readonly viewportPlugin: ViewportPlugin;\n private readonly scroll: ScrollCapability;\n private readonly interactionManager: InteractionManagerCapability | null;\n private readonly presets: ZoomPreset[];\n private readonly zoomRanges: ZoomRangeStep[];\n\n private readonly minZoom: number;\n private readonly maxZoom: number;\n private readonly zoomStep: number;\n\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 this.minZoom = cfg.minZoom ?? 0.25;\n this.maxZoom = cfg.maxZoom ?? 10;\n this.zoomStep = cfg.zoomStep ?? 0.1;\n this.presets = cfg.presets ?? [];\n this.zoomRanges = this.normalizeRanges(cfg.zoomRanges ?? []);\n this.dispatch(setInitialZoomLevel(cfg.defaultZoomLevel));\n /* keep \"automatic\" modes up to date -------------------------------- */\n this.viewport.onViewportResize(() => this.recalcAuto(VerticalZoomFocus.Top), {\n mode: 'debounce',\n wait: 150,\n });\n this.coreStore.onAction(SET_ROTATION, () => this.recalcAuto(VerticalZoomFocus.Top));\n this.coreStore.onAction(SET_PAGES, () => this.recalcAuto(VerticalZoomFocus.Top));\n this.coreStore.onAction(SET_DOCUMENT, () => this.recalcAuto(VerticalZoomFocus.Top));\n this.interactionManager?.registerMode({\n id: 'marqueeZoom',\n scope: 'page',\n exclusive: true,\n cursor: 'zoom-in',\n });\n this.resetReady();\n }\n\n /* ------------------------------------------------------------------ */\n /* capability */\n /* ------------------------------------------------------------------ */\n protected buildCapability(): ZoomCapability {\n return {\n onZoomChange: this.zoom$.on,\n onStateChange: this.state$.on,\n zoomIn: () => this.zoomIn(),\n zoomOut: () => this.zoomOut(),\n zoomToArea: (pageIndex, rect) => this.zoomToArea(pageIndex, rect),\n requestZoom: (level, c) => this.handleRequest({ level, center: c }),\n requestZoomBy: (d, c) => {\n const cur = this.state.currentZoomLevel;\n const target = this.toZoom(cur + d);\n return this.handleRequest({ level: target, center: c });\n },\n enableMarqueeZoom: () => {\n this.interactionManager?.activate('marqueeZoom');\n },\n disableMarqueeZoom: () => {\n this.interactionManager?.activateDefaultMode();\n },\n toggleMarqueeZoom: () => {\n if (this.interactionManager?.getActiveMode() === 'marqueeZoom') {\n this.interactionManager?.activateDefaultMode();\n } else {\n this.interactionManager?.activate('marqueeZoom');\n }\n },\n isMarqueeZoomActive: () => this.interactionManager?.getActiveMode() === 'marqueeZoom',\n registerMarqueeOnPage: (opts) => this.registerMarqueeOnPage(opts),\n getState: () => this.state,\n getPresets: () => this.presets,\n };\n }\n\n private zoomOut() {\n const cur = this.state.currentZoomLevel;\n return this.handleRequest({ level: cur, delta: -this.stepFor(cur) });\n }\n\n private zoomIn() {\n const cur = this.state.currentZoomLevel;\n return this.handleRequest({ level: cur, delta: this.stepFor(cur) });\n }\n\n private zoomToArea(pageIndex: number, rect: Rect) {\n this.handleZoomToArea(pageIndex, rect);\n }\n\n /* ------------------------------------------------------------------ */\n /* plugin life‑cycle */\n /* ------------------------------------------------------------------ */\n async initialize(): Promise<void> {\n /* apply the initial zoom\n /* Mark plugin as ready - zoom will be calculated when viewport has dimensions */\n this.markReady();\n }\n\n async destroy() {\n this.zoom$.clear();\n }\n\n /**\n * Sort ranges once, make sure they are sane\n */\n private normalizeRanges(ranges: ZoomRangeStep[]): ZoomRangeStep[] {\n return [...ranges]\n .filter((r) => r.step > 0 && r.max > r.min) // basic sanity\n .sort((a, b) => a.min - b.min);\n }\n\n /** pick the step that applies to a given numeric zoom */\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; // fallback\n }\n\n /** clamp + round helper reused later */\n private toZoom(v: number) {\n return parseFloat(clamp(v, this.minZoom, this.maxZoom).toFixed(2));\n }\n\n /* ------------------------------------------------------------------ */\n /* main entry – handles **every** zoom request */\n /* ------------------------------------------------------------------ */\n private handleRequest({\n level,\n delta = 0,\n center,\n focus = VerticalZoomFocus.Center,\n align = 'keep',\n }: ZoomRequest) {\n const metrics = this.viewport.getMetrics();\n const oldZoom = this.state.currentZoomLevel;\n\n if (metrics.clientWidth === 0 || metrics.clientHeight === 0) {\n return;\n }\n\n /* ------------------------------------------------------------------ */\n /* step 1 – resolve the **target numeric zoom** */\n /* ------------------------------------------------------------------ */\n const base = typeof level === 'number' ? level : this.computeZoomForMode(level, metrics);\n\n if (base === false) {\n return;\n }\n const exactZoom = clamp(base + delta, this.minZoom, this.maxZoom);\n const newZoom = Math.floor(exactZoom * 100) / 100;\n\n /* ------------------------------------------------------------------ */\n /* step 2 – figure out the viewport point we should keep under focus */\n /* ------------------------------------------------------------------ */\n const focusPoint: Point = center ?? {\n vx: metrics.clientWidth / 2,\n vy: focus === VerticalZoomFocus.Top ? 0 : metrics.clientHeight / 2,\n };\n\n /* ------------------------------------------------------------------ */\n /* step 3 – translate that into desired scroll offsets */\n /* ------------------------------------------------------------------ */\n const { desiredScrollLeft, desiredScrollTop } = this.computeScrollForZoomChange(\n metrics,\n oldZoom,\n newZoom,\n focusPoint,\n align,\n );\n\n /* ------------------------------------------------------------------ */\n /* step 4 – dispatch + notify */\n /* ------------------------------------------------------------------ */\n\n if (!isNaN(desiredScrollLeft) && !isNaN(desiredScrollTop)) {\n this.viewportPlugin.setViewportScrollMetrics({\n scrollLeft: desiredScrollLeft,\n scrollTop: desiredScrollTop,\n });\n }\n\n this.dispatch(setZoomLevel(typeof level === 'number' ? newZoom : level, newZoom));\n this.dispatchCoreAction(setScale(newZoom));\n this.markReady();\n\n this.viewport.scrollTo({\n x: desiredScrollLeft,\n y: desiredScrollTop,\n behavior: 'instant',\n });\n\n const evt: ZoomChangeEvent = {\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 /* ------------------------------------------------------------------ */\n /* helpers */\n /* ------------------------------------------------------------------ */\n\n /** numeric zoom for Automatic / FitPage / FitWidth */\n private computeZoomForMode(mode: ZoomMode, vp: ViewportMetrics): number | false {\n const spreads = getPagesWithRotatedSize(this.coreState.core);\n if (!spreads.length) return false;\n\n const pgGap = this.scroll.getPageGap();\n const vpGap = this.viewport.getViewportGap();\n\n if (vp.clientWidth === 0 || vp.clientHeight === 0) {\n return false;\n }\n\n // Available space after accounting for fixed viewport gaps\n const availableWidth = vp.clientWidth - 2 * vpGap;\n const availableHeight = vp.clientHeight - 2 * vpGap;\n\n if (availableWidth <= 0 || availableHeight <= 0) {\n return false;\n }\n\n let maxContentW = 0,\n maxContentH = 0;\n\n spreads.forEach((spread) => {\n // Only include scalable content (pages + page gaps), not viewport gaps\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 /* istanbul ignore next */\n default:\n return 1;\n }\n }\n\n /** where to scroll so that *focus* stays stable after scaling */\n private computeScrollForZoomChange(\n vp: ViewportMetrics,\n oldZoom: number,\n newZoom: number,\n focus: Point,\n align: 'keep' | 'center' = 'keep',\n ) {\n /* unscaled content size ------------------------------------------- */\n const layout = this.scroll.getLayout();\n const vpGap = this.viewport.getViewportGap();\n\n const contentW = layout.totalContentSize.width;\n const contentH = layout.totalContentSize.height;\n\n // Available space for content (excluding fixed viewport gaps)\n const availableWidth = vp.clientWidth - 2 * vpGap;\n const availableHeight = vp.clientHeight - 2 * vpGap;\n\n /* helper: offset if content is narrower than available space ------- */\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 /* content coords of the focal point -------------------------------- */\n // Adjust focus point to account for vpGap and centering offset\n const cx = (vp.scrollLeft + focus.vx - vpGap - offXold) / oldZoom;\n const cy = (vp.scrollTop + focus.vy - vpGap - offYold) / oldZoom;\n\n /* new scroll so that (cx,cy) appears under focus again ------------- */\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(pageIndex: number, rect: Rect) {\n /* -------------------------------------------------- */\n /* 0 – rotation that applies to this page */\n /* -------------------------------------------------- */\n const rotation = this.coreState.core.rotation;\n\n /* -------------------------------------------------- */\n /* viewport + layout basics */\n /* -------------------------------------------------- */\n const vp = this.viewport.getMetrics();\n const vpGap = this.viewport.getViewportGap();\n const oldZ = this.state.currentZoomLevel;\n\n const availableW = vp.clientWidth - 2 * vpGap;\n const availableH = vp.clientHeight - 2 * vpGap;\n\n const layout = this.scroll.getLayout();\n\n /* which virtual item holds the page? */\n const vItem = layout.virtualItems.find((it) =>\n it.pageLayouts.some((p) => p.pageIndex === pageIndex),\n );\n if (!vItem) return;\n\n /* the page layout inside that virtual item */\n const pageRel = vItem.pageLayouts.find((p) => p.pageIndex === pageIndex)!;\n\n /* -------------------------------------------------- */\n /* 1 – rect → rotated‑page space */\n /* -------------------------------------------------- */\n const rotatedRect = rotateRect(\n {\n width: pageRel.width,\n height: pageRel.height,\n },\n rect,\n rotation,\n );\n\n /* -------------------------------------------------- */\n /* 2 – numeric zoom so the rect fits */\n /* -------------------------------------------------- */\n const targetZoom = this.toZoom(\n Math.min(availableW / rotatedRect.size.width, availableH / rotatedRect.size.height),\n );\n\n /* -------------------------------------------------- */\n /* 3 – centre of that rect in *content* coordinates */\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 /* -------------------------------------------------- */\n /* 4 – centre in *viewport* coords before zoom */\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 /* -------------------------------------------------- */\n /* 5 – hand off to the generic zoom handler */\n /* -------------------------------------------------- */\n this.handleRequest({\n level: targetZoom,\n center: { vx: centerVX, vy: centerVY },\n align: 'center',\n });\n }\n\n /** recalculates Automatic / Fit* when viewport or pages change */\n private recalcAuto(focus?: VerticalZoomFocus) {\n const s = this.state;\n if (\n s.zoomLevel === ZoomMode.Automatic ||\n s.zoomLevel === ZoomMode.FitPage ||\n s.zoomLevel === ZoomMode.FitWidth\n )\n this.handleRequest({ level: s.zoomLevel, focus });\n }\n\n override onStoreUpdated(_prevState: ZoomState, newState: ZoomState): void {\n this.state$.emit(newState);\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 document = this.coreState.core.document;\n if (!document) {\n this.logger.warn('ZoomPlugin', 'DocumentNotFound', 'Document not found');\n return () => {};\n }\n\n const page = 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 // Large drag → zoom to the selected area\n this.zoomToArea(opts.pageIndex, rect);\n opts.callback.onCommit?.(rect);\n },\n onSmallDrag: () => {\n // Small drag → simple zoom in\n this.zoomIn();\n opts.callback.onSmallDrag?.();\n },\n });\n\n const off = this.interactionManager.registerHandlers({\n modeId: 'marqueeZoom',\n handlers,\n pageIndex: opts.pageIndex,\n });\n\n return off;\n }\n}\n","import { PluginPackage } from '@embedpdf/core';\n\nimport { ZoomAction } from './actions';\nimport { manifest, ZOOM_PLUGIN_ID } from './manifest';\nimport { zoomReducer, initialState } 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 };\n"],"names":["ZoomMode","VerticalZoomFocus","r"],"mappings":"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"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
interface MarqueeZoomProps {
|
|
2
|
+
/** Index of the page this layer lives on */
|
|
3
|
+
pageIndex: number;
|
|
4
|
+
/** Scale of the page */
|
|
5
|
+
scale: number;
|
|
6
|
+
/** Optional CSS class applied to the marquee rectangle */
|
|
7
|
+
className?: string;
|
|
8
|
+
/** Stroke / fill colours (defaults below) */
|
|
9
|
+
stroke?: string;
|
|
10
|
+
fill?: string;
|
|
11
|
+
}
|
|
12
|
+
export declare const MarqueeZoom: ({ pageIndex, scale, className, stroke, fill, }: MarqueeZoomProps) => import("react/jsx-runtime").JSX.Element | null;
|
|
13
|
+
export {};
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { ReactNode, HTMLAttributes, CSSProperties } from '../../react/adapter.ts';
|
|
2
|
+
type PinchWrapperProps = Omit<HTMLAttributes<HTMLDivElement>, 'style'> & {
|
|
3
|
+
children: ReactNode;
|
|
4
|
+
style?: CSSProperties;
|
|
5
|
+
};
|
|
6
|
+
export declare function PinchWrapper({ children, style, ...props }: PinchWrapperProps): import("react/jsx-runtime").JSX.Element;
|
|
7
|
+
export {};
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { ZoomPlugin, ZoomState } from '../../index.ts';
|
|
2
|
+
export declare const useZoomCapability: () => {
|
|
3
|
+
provides: Readonly<import('../../index.ts').ZoomCapability> | null;
|
|
4
|
+
isLoading: boolean;
|
|
5
|
+
ready: Promise<void>;
|
|
6
|
+
};
|
|
7
|
+
export declare const useZoomPlugin: () => {
|
|
8
|
+
plugin: ZoomPlugin | null;
|
|
9
|
+
isLoading: boolean;
|
|
10
|
+
ready: Promise<void>;
|
|
11
|
+
};
|
|
12
|
+
export declare const useZoom: () => {
|
|
13
|
+
state: ZoomState;
|
|
14
|
+
provides: Readonly<import('../../index.ts').ZoomCapability> | null;
|
|
15
|
+
};
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { ViewportCapability } from '@embedpdf/plugin-viewport';
|
|
2
|
+
import { ZoomCapability } from '../../index.ts';
|
|
3
|
+
export interface PinchZoomDeps {
|
|
4
|
+
element: HTMLDivElement;
|
|
5
|
+
viewportProvides: ViewportCapability;
|
|
6
|
+
zoomProvides: ZoomCapability;
|
|
7
|
+
}
|
|
8
|
+
export declare function setupPinchZoom({ element, viewportProvides, zoomProvides }: PinchZoomDeps): () => void;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { ViewportCapability } from '@embedpdf/plugin-viewport';
|
|
2
|
+
import { ZoomCapability } from '../../lib/index.ts';
|
|
3
|
+
export interface PinchZoomDeps {
|
|
4
|
+
element: HTMLDivElement;
|
|
5
|
+
viewportProvides: ViewportCapability;
|
|
6
|
+
zoomProvides: ZoomCapability;
|
|
7
|
+
}
|
|
8
|
+
export declare function setupPinchZoom({ element, viewportProvides, zoomProvides }: PinchZoomDeps): () => void;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
interface MarqueeZoomProps {
|
|
2
|
+
/** Index of the page this layer lives on */
|
|
3
|
+
pageIndex: number;
|
|
4
|
+
/** Scale of the page */
|
|
5
|
+
scale: number;
|
|
6
|
+
/** Optional CSS class applied to the marquee rectangle */
|
|
7
|
+
class?: string;
|
|
8
|
+
/** Stroke / fill colours (defaults below) */
|
|
9
|
+
stroke?: string;
|
|
10
|
+
fill?: string;
|
|
11
|
+
}
|
|
12
|
+
declare const MarqueeZoom: import('svelte', { with: { "resolution-mode": "import" } }).Component<MarqueeZoomProps, {}, "">;
|
|
13
|
+
type MarqueeZoom = ReturnType<typeof MarqueeZoom>;
|
|
14
|
+
export default MarqueeZoom;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { Snippet } from 'svelte';
|
|
2
|
+
import { HTMLAttributes } from 'svelte/elements';
|
|
3
|
+
type PinchWrapperProps = Omit<HTMLAttributes<HTMLDivElement>, 'style'> & {
|
|
4
|
+
children: Snippet;
|
|
5
|
+
class?: string;
|
|
6
|
+
};
|
|
7
|
+
declare const PinchWrapper: import('svelte', { with: { "resolution-mode": "import" } }).Component<PinchWrapperProps, {}, "">;
|
|
8
|
+
type PinchWrapper = ReturnType<typeof PinchWrapper>;
|
|
9
|
+
export default PinchWrapper;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { ZoomPlugin, ZoomState } from '../../lib/index.ts';
|
|
2
|
+
export declare const useZoomCapability: () => {
|
|
3
|
+
provides: Readonly<import('../../lib/index.ts').ZoomCapability> | null;
|
|
4
|
+
isLoading: boolean;
|
|
5
|
+
ready: Promise<void>;
|
|
6
|
+
};
|
|
7
|
+
export declare const useZoomPlugin: () => {
|
|
8
|
+
plugin: ZoomPlugin | null;
|
|
9
|
+
isLoading: boolean;
|
|
10
|
+
ready: Promise<void>;
|
|
11
|
+
};
|
|
12
|
+
export declare const useZoom: () => {
|
|
13
|
+
readonly state: ZoomState;
|
|
14
|
+
readonly provides: Readonly<import('../../lib/index.ts').ZoomCapability> | null;
|
|
15
|
+
};
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("svelte/internal/client"),t=require("@embedpdf/plugin-zoom"),r=require("@embedpdf/core/svelte");function i(e){const t=Object.create(null,{[Symbol.toStringTag]:{value:"Module"}});if(e)for(const r in e)if("default"!==r){const i=Object.getOwnPropertyDescriptor(e,r);Object.defineProperty(t,r,i.get?i:{enumerable:!0,get:()=>e[r]})}return t.default=e,Object.freeze(t)}require("svelte/internal/disclose-version");const o=i(e),s=()=>r.useCapability(t.ZoomPlugin.id);function n(){const e=o.derived((()=>r.useCapability("viewport")));o.derived((()=>o.get(e).provides));const t=o.derived(s);o.derived((()=>o.get(t).provides));return o.user_effect((()=>{})),{get elementRef(){return null}}}var l=o.from_html("<div></div>");var a=o.from_html("<div> </div> }",1);exports.MarqueeZoom=function(e,t){o.push(t,!0);let r=o.prop(t,"stroke",3,"rgba(33,150,243,0.8)"),i=o.prop(t,"fill",3,"rgba(33,150,243,0.15)");const n=o.derived(s),a=o.derived((()=>o.get(n).provides));let d=o.state(null);o.user_effect((()=>{if(o.get(a))return o.get(a).registerMarqueeOnPage({pageIndex:t.pageIndex,scale:t.scale,callback:{onPreview:e=>o.set(d,e,!0)}})}));var p=o.comment(),c=o.first_child(p),u=e=>{var s=l();let n;o.template_effect((e=>{o.set_class(s,1,o.clsx(t.class)),n=o.set_style(s,"",n,e)}),[()=>({position:"absolute","pointer-events":"none",left:o.get(d).origin.x*t.scale+"px",top:o.get(d).origin.y*t.scale+"px",width:o.get(d).size.width*t.scale+"px",height:o.get(d).size.height*t.scale+"px",border:`1px solid ${r()}`,background:i(),"box-sizing":"border-box"})]),o.append(e,s)};o.if(c,(e=>{o.get(d)&&e(u)})),o.append(e,p),o.pop()},exports.PinchWrapper=function(e,t){o.push(t,!0);let r=o.rest_props(t,["$$slots","$$events","$$legacy","children","class"]);const i=o.derived(n),s=o.derived((()=>o.get(i).elementRef));var l=a(),d=o.first_child(l);o.attribute_effect(d,(()=>({ref:o.get(s),...r,class:t.class,[o.STYLE]:{display:"block",width:"fit-content",overflow:"visible","box-sizing":"border-box",margin:"0px auto"}})));var p=o.child(d,!0);o.reset(d),o.next(),o.template_effect((()=>o.set_text(p,t.children))),o.append(e,l),o.pop()},exports.usePinch=n,exports.useZoom=()=>{const e=o.derived(s),r=o.derived((()=>o.get(e).provides));let i=o.state(o.proxy(t.initialState));return o.user_effect((()=>{var e;return null==(e=o.get(r))?void 0:e.onStateChange((e=>{o.set(i,e,!0)}))})),{get state(){return o.get(i)},get provides(){return o.get(r)}}},exports.useZoomCapability=s,exports.useZoomPlugin=()=>r.usePlugin(t.ZoomPlugin.id),Object.keys(t).forEach((e=>{"default"===e||Object.prototype.hasOwnProperty.call(exports,e)||Object.defineProperty(exports,e,{enumerable:!0,get:()=>t[e]})}));
|
|
2
|
+
//# sourceMappingURL=index.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.cjs","sources":["../../src/svelte/hooks/use-zoom.svelte.ts","../../src/svelte/hooks/use-pinch-zoom.svelte.ts","../../src/svelte/components/MarqueeZoom.svelte","../../src/svelte/components/PinchWrapper.svelte"],"sourcesContent":["import { initialState, ZoomPlugin, ZoomState } from '@embedpdf/plugin-zoom';\nimport { useCapability, usePlugin } from '@embedpdf/core/svelte';\n\nexport const useZoomCapability = () => useCapability<ZoomPlugin>(ZoomPlugin.id);\nexport const useZoomPlugin = () => usePlugin<ZoomPlugin>(ZoomPlugin.id);\n\nexport const useZoom = () => {\n const { provides } = $derived(useZoomCapability());\n let zoomState = $state<ZoomState>(initialState);\n\n $effect(() => {\n return provides?.onStateChange((action) => {\n zoomState = action;\n });\n });\n\n return {\n get state() {\n return zoomState;\n },\n get provides() {\n return provides;\n },\n };\n};\n","import type { ViewportPlugin } from '@embedpdf/plugin-viewport';\nimport { useZoomCapability } from './use-zoom.svelte';\nimport { useCapability } from '@embedpdf/core/svelte';\nimport { setupPinchZoom } from '../../shared/utils/pinch-zoom-logic';\n\nexport function usePinch() {\n const { provides: viewportProvides } = $derived(useCapability<ViewportPlugin>('viewport'));\n const { provides: zoomProvides } = $derived(useZoomCapability());\n const elementRef = $state<HTMLDivElement | null>(null);\n\n $effect(() => {\n const element = elementRef;\n if (!element || !viewportProvides || !zoomProvides) {\n return;\n }\n\n return setupPinchZoom({ element, viewportProvides, zoomProvides });\n });\n\n return {\n get elementRef() {\n return elementRef;\n },\n };\n}\n","<script lang=\"ts\">\n import type { Rect } from '@embedpdf/models';\n import { useZoomCapability } from '../hooks/use-zoom.svelte';\n\n interface MarqueeZoomProps {\n /** Index of the page this layer lives on */\n pageIndex: number;\n /** Scale of the page */\n scale: number;\n /** Optional CSS class applied to the marquee rectangle */\n class?: string;\n /** Stroke / fill colours (defaults below) */\n stroke?: string;\n fill?: string;\n }\n\n let {\n pageIndex,\n scale,\n class: propsClass,\n stroke = 'rgba(33,150,243,0.8)',\n fill = 'rgba(33,150,243,0.15)',\n }: MarqueeZoomProps = $props();\n\n const { provides: zoomPlugin } = $derived(useZoomCapability());\n let rect = $state<Rect | null>(null);\n\n $effect(() => {\n if (!zoomPlugin) return;\n return zoomPlugin.registerMarqueeOnPage({\n pageIndex,\n scale,\n callback: { onPreview: (val) => (rect = val) },\n });\n });\n</script>\n\n{#if rect}\n <div\n style:position=\"absolute\"\n style:pointer-events=\"none\"\n style:left={`${rect.origin.x * scale}px`}\n style:top={`${rect.origin.y * scale}px`}\n style:width={`${rect.size.width * scale}px`}\n style:height={`${rect.size.height * scale}px`}\n style:border={`1px solid ${stroke}`}\n style:background={fill}\n style:box-sizing=\"border-box\"\n class={propsClass}\n ></div>\n{/if}\n","<script lang=\"ts\">\n import { usePinch } from '../hooks';\n import type { Snippet } from 'svelte';\n import type { HTMLAttributes } from 'svelte/elements';\n\n type PinchWrapperProps = Omit<HTMLAttributes<HTMLDivElement>, 'style'> & {\n children: Snippet;\n class?: string;\n };\n\n let { children, class: propsClass, ...restProps }: PinchWrapperProps = $props();\n const { elementRef } = $derived(usePinch());\n</script>\n\n<div\n ref={elementRef}\n {...restProps}\n style:display=\"block\"\n style:width=\"fit-content\"\n style:overflow=\"visible\"\n style:box-sizing=\"border-box\"\n style:margin=\"0px auto\"\n class={propsClass}\n>\n {children}\n</div>\n\n}\n"],"names":["useZoomCapability","useCapability","ZoomPlugin","id","usePinch","$$d","$","derived","provides","user_effect","elementRef","stroke","fill","zoomPlugin","rect","get","registerMarqueeOnPage","pageIndex","$$props","scale","callback","onPreview","val","set","origin","x","y","size","width","height","consequent","restProps","rest_props","zoomState","initialState","_a","onStateChange","action","$__namespace","state","usePlugin"],"mappings":"ogBAGaA,EAA0B,IAAAC,gBAA0BC,EAAAA,WAAWC,ICE5D,SAAAC,IACkC,MAAAC,EAAAC,EAAAC,SAAA,IAAAN,EAAAA,cAA8B,sCAAtEO,6BACoCR,2BAApCQ,kBAGRF,EAAAG,uBAUM,cAAAC,GACK,OAbsC,MAgBnD,uHCJI,IAAAC,sBAAS,wBACTC,oBAAO,2CAGiCZ,GAAxBa,0BAAVL,WACJ,IAAAM,UAA2B,MAE/BR,EAAAG,aAAc,cACPI,GACE,OAAAP,EAAAS,IAAAF,GAAWG,sBAAqB,CACrCC,UAASC,EAAAD,UACTE,MAAKD,EAAAC,MACLC,UAAYC,UAAYC,GAAShB,EAAAiB,IAAAT,EAAOQ,GAAG,oNAS9BR,GAAKU,OAAOC,EAACP,EAAAC,qBACdL,GAAKU,OAAOE,EAACR,EAAAC,uBACXL,GAAKa,KAAKC,MAAKV,EAAAC,wBACdL,GAAKa,KAAKE,OAAMX,EAAAC,+BACNR,iBACTC,mEATjBE,MAAIgB,EAAA,yBAFT,kDCzBwC,IAAAC,EAASzB,EAAA0B,WAAAd,EAAA,CAAA,UAAA,WAAA,WAAA,WAAA,4BACfd,GAAxBM,0BAAAA,gFAIHA,MACDqB,kPAJN,4DHLgC/B,GAAtBQ,0BAAAA,WACJ,IAAAyB,kBAA8BC,EAAAA,sBAElC5B,EAAAG,wBACS,OAAAH,OAAAA,IAAAS,IAAAP,SAAU,EAAA2B,EAAAC,eAAeC,IAClBC,EAAAf,IAAAU,EAAAI,GAAA,EAAA,QAKV,SAAAE,gBACKN,EACT,EACI,YAAAzB,gBACKA,wDAjBsB,IAAAgC,YAAsBtC,EAAAA,WAAWC"}
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
import * as $ from "svelte/internal/client";
|
|
2
|
+
import { ZoomPlugin, initialState } from "@embedpdf/plugin-zoom";
|
|
3
|
+
export * from "@embedpdf/plugin-zoom";
|
|
4
|
+
import { useCapability, usePlugin } from "@embedpdf/core/svelte";
|
|
5
|
+
import "svelte/internal/disclose-version";
|
|
6
|
+
const useZoomCapability = () => useCapability(ZoomPlugin.id);
|
|
7
|
+
const useZoomPlugin = () => usePlugin(ZoomPlugin.id);
|
|
8
|
+
const useZoom = () => {
|
|
9
|
+
const $$d = $.derived(useZoomCapability), provides = $.derived(() => $.get($$d).provides);
|
|
10
|
+
let zoomState = $.state($.proxy(initialState));
|
|
11
|
+
$.user_effect(() => {
|
|
12
|
+
var _a;
|
|
13
|
+
return (_a = $.get(provides)) == null ? void 0 : _a.onStateChange((action) => {
|
|
14
|
+
$.set(zoomState, action, true);
|
|
15
|
+
});
|
|
16
|
+
});
|
|
17
|
+
return {
|
|
18
|
+
get state() {
|
|
19
|
+
return $.get(zoomState);
|
|
20
|
+
},
|
|
21
|
+
get provides() {
|
|
22
|
+
return $.get(provides);
|
|
23
|
+
}
|
|
24
|
+
};
|
|
25
|
+
};
|
|
26
|
+
function usePinch() {
|
|
27
|
+
const $$d = $.derived(() => useCapability("viewport"));
|
|
28
|
+
$.derived(() => $.get($$d).provides);
|
|
29
|
+
const $$d_1 = $.derived(useZoomCapability);
|
|
30
|
+
$.derived(() => $.get($$d_1).provides);
|
|
31
|
+
const elementRef = null;
|
|
32
|
+
$.user_effect(() => {
|
|
33
|
+
{
|
|
34
|
+
return;
|
|
35
|
+
}
|
|
36
|
+
});
|
|
37
|
+
return {
|
|
38
|
+
get elementRef() {
|
|
39
|
+
return elementRef;
|
|
40
|
+
}
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
var root_1 = $.from_html(`<div></div>`);
|
|
44
|
+
function MarqueeZoom($$anchor, $$props) {
|
|
45
|
+
$.push($$props, true);
|
|
46
|
+
let stroke = $.prop($$props, "stroke", 3, "rgba(33,150,243,0.8)"), fill = $.prop($$props, "fill", 3, "rgba(33,150,243,0.15)");
|
|
47
|
+
const $$d = $.derived(useZoomCapability), zoomPlugin = $.derived(() => $.get($$d).provides);
|
|
48
|
+
let rect = $.state(null);
|
|
49
|
+
$.user_effect(() => {
|
|
50
|
+
if (!$.get(zoomPlugin)) return;
|
|
51
|
+
return $.get(zoomPlugin).registerMarqueeOnPage({
|
|
52
|
+
pageIndex: $$props.pageIndex,
|
|
53
|
+
scale: $$props.scale,
|
|
54
|
+
callback: { onPreview: (val) => $.set(rect, val, true) }
|
|
55
|
+
});
|
|
56
|
+
});
|
|
57
|
+
var fragment = $.comment();
|
|
58
|
+
var node = $.first_child(fragment);
|
|
59
|
+
{
|
|
60
|
+
var consequent = ($$anchor2) => {
|
|
61
|
+
var div = root_1();
|
|
62
|
+
let styles;
|
|
63
|
+
$.template_effect(
|
|
64
|
+
($0) => {
|
|
65
|
+
$.set_class(div, 1, $.clsx($$props.class));
|
|
66
|
+
styles = $.set_style(div, "", styles, $0);
|
|
67
|
+
},
|
|
68
|
+
[
|
|
69
|
+
() => ({
|
|
70
|
+
position: "absolute",
|
|
71
|
+
"pointer-events": "none",
|
|
72
|
+
left: `${$.get(rect).origin.x * $$props.scale}px`,
|
|
73
|
+
top: `${$.get(rect).origin.y * $$props.scale}px`,
|
|
74
|
+
width: `${$.get(rect).size.width * $$props.scale}px`,
|
|
75
|
+
height: `${$.get(rect).size.height * $$props.scale}px`,
|
|
76
|
+
border: `1px solid ${stroke()}`,
|
|
77
|
+
background: fill(),
|
|
78
|
+
"box-sizing": "border-box"
|
|
79
|
+
})
|
|
80
|
+
]
|
|
81
|
+
);
|
|
82
|
+
$.append($$anchor2, div);
|
|
83
|
+
};
|
|
84
|
+
$.if(node, ($$render) => {
|
|
85
|
+
if ($.get(rect)) $$render(consequent);
|
|
86
|
+
});
|
|
87
|
+
}
|
|
88
|
+
$.append($$anchor, fragment);
|
|
89
|
+
$.pop();
|
|
90
|
+
}
|
|
91
|
+
var root = $.from_html(`<div> </div> }`, 1);
|
|
92
|
+
function PinchWrapper($$anchor, $$props) {
|
|
93
|
+
$.push($$props, true);
|
|
94
|
+
let restProps = $.rest_props($$props, ["$$slots", "$$events", "$$legacy", "children", "class"]);
|
|
95
|
+
const $$d = $.derived(usePinch), elementRef = $.derived(() => $.get($$d).elementRef);
|
|
96
|
+
var fragment = root();
|
|
97
|
+
var div = $.first_child(fragment);
|
|
98
|
+
$.attribute_effect(div, () => ({
|
|
99
|
+
ref: $.get(elementRef),
|
|
100
|
+
...restProps,
|
|
101
|
+
class: $$props.class,
|
|
102
|
+
[$.STYLE]: {
|
|
103
|
+
display: "block",
|
|
104
|
+
width: "fit-content",
|
|
105
|
+
overflow: "visible",
|
|
106
|
+
"box-sizing": "border-box",
|
|
107
|
+
margin: "0px auto"
|
|
108
|
+
}
|
|
109
|
+
}));
|
|
110
|
+
var text = $.child(div, true);
|
|
111
|
+
$.reset(div);
|
|
112
|
+
$.next();
|
|
113
|
+
$.template_effect(() => $.set_text(text, $$props.children));
|
|
114
|
+
$.append($$anchor, fragment);
|
|
115
|
+
$.pop();
|
|
116
|
+
}
|
|
117
|
+
export {
|
|
118
|
+
MarqueeZoom,
|
|
119
|
+
PinchWrapper,
|
|
120
|
+
usePinch,
|
|
121
|
+
useZoom,
|
|
122
|
+
useZoomCapability,
|
|
123
|
+
useZoomPlugin
|
|
124
|
+
};
|
|
125
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sources":["../../src/svelte/hooks/use-zoom.svelte.ts","../../src/svelte/hooks/use-pinch-zoom.svelte.ts","../../src/svelte/components/MarqueeZoom.svelte","../../src/svelte/components/PinchWrapper.svelte"],"sourcesContent":["import { initialState, ZoomPlugin, ZoomState } from '@embedpdf/plugin-zoom';\nimport { useCapability, usePlugin } from '@embedpdf/core/svelte';\n\nexport const useZoomCapability = () => useCapability<ZoomPlugin>(ZoomPlugin.id);\nexport const useZoomPlugin = () => usePlugin<ZoomPlugin>(ZoomPlugin.id);\n\nexport const useZoom = () => {\n const { provides } = $derived(useZoomCapability());\n let zoomState = $state<ZoomState>(initialState);\n\n $effect(() => {\n return provides?.onStateChange((action) => {\n zoomState = action;\n });\n });\n\n return {\n get state() {\n return zoomState;\n },\n get provides() {\n return provides;\n },\n };\n};\n","import type { ViewportPlugin } from '@embedpdf/plugin-viewport';\nimport { useZoomCapability } from './use-zoom.svelte';\nimport { useCapability } from '@embedpdf/core/svelte';\nimport { setupPinchZoom } from '../../shared/utils/pinch-zoom-logic';\n\nexport function usePinch() {\n const { provides: viewportProvides } = $derived(useCapability<ViewportPlugin>('viewport'));\n const { provides: zoomProvides } = $derived(useZoomCapability());\n const elementRef = $state<HTMLDivElement | null>(null);\n\n $effect(() => {\n const element = elementRef;\n if (!element || !viewportProvides || !zoomProvides) {\n return;\n }\n\n return setupPinchZoom({ element, viewportProvides, zoomProvides });\n });\n\n return {\n get elementRef() {\n return elementRef;\n },\n };\n}\n","<script lang=\"ts\">\n import type { Rect } from '@embedpdf/models';\n import { useZoomCapability } from '../hooks/use-zoom.svelte';\n\n interface MarqueeZoomProps {\n /** Index of the page this layer lives on */\n pageIndex: number;\n /** Scale of the page */\n scale: number;\n /** Optional CSS class applied to the marquee rectangle */\n class?: string;\n /** Stroke / fill colours (defaults below) */\n stroke?: string;\n fill?: string;\n }\n\n let {\n pageIndex,\n scale,\n class: propsClass,\n stroke = 'rgba(33,150,243,0.8)',\n fill = 'rgba(33,150,243,0.15)',\n }: MarqueeZoomProps = $props();\n\n const { provides: zoomPlugin } = $derived(useZoomCapability());\n let rect = $state<Rect | null>(null);\n\n $effect(() => {\n if (!zoomPlugin) return;\n return zoomPlugin.registerMarqueeOnPage({\n pageIndex,\n scale,\n callback: { onPreview: (val) => (rect = val) },\n });\n });\n</script>\n\n{#if rect}\n <div\n style:position=\"absolute\"\n style:pointer-events=\"none\"\n style:left={`${rect.origin.x * scale}px`}\n style:top={`${rect.origin.y * scale}px`}\n style:width={`${rect.size.width * scale}px`}\n style:height={`${rect.size.height * scale}px`}\n style:border={`1px solid ${stroke}`}\n style:background={fill}\n style:box-sizing=\"border-box\"\n class={propsClass}\n ></div>\n{/if}\n","<script lang=\"ts\">\n import { usePinch } from '../hooks';\n import type { Snippet } from 'svelte';\n import type { HTMLAttributes } from 'svelte/elements';\n\n type PinchWrapperProps = Omit<HTMLAttributes<HTMLDivElement>, 'style'> & {\n children: Snippet;\n class?: string;\n };\n\n let { children, class: propsClass, ...restProps }: PinchWrapperProps = $props();\n const { elementRef } = $derived(usePinch());\n</script>\n\n<div\n ref={elementRef}\n {...restProps}\n style:display=\"block\"\n style:width=\"fit-content\"\n style:overflow=\"visible\"\n style:box-sizing=\"border-box\"\n style:margin=\"0px auto\"\n class={propsClass}\n>\n {children}\n</div>\n\n}\n"],"names":[],"mappings":";;;;;AAGa,MAAA,oBAA0B,MAAA,cAA0B,WAAW,EAAE;AACjE,MAAA,gBAAsB,MAAA,UAAsB,WAAW,EAAE;AAEzD,MAAA,gBAAgB;wBACG,oBAAtB,sCAAA,QAAA;AACJ,MAAA,4BAA8B,YAAY,CAAA;AAE9C,IAAA,kBAAc;;AACL,YAAA,OAAA,IAAA,QAAA,MAAA,mBAAU,cAAe,CAAA,WAAW;AAC7B,QAAA,IAAA,WAAA,QAAA,IAAA;AAAA;GAEf;;IAGK,IAAA,QAAQ;mBACH,SAAA;AAAA,IACT;AAAA,IACI,IAAA,WAAW;mBACN,QAAA;AAAA;;AAGb;ACnBgB,SAAA,WAAW;AACuB,QAAA,MAAA,EAAA,QAAA,MAAA,cAA8B,UAAU,CAAA;6BAAhF,QAAU;0BAC0B;+BAApC,QAAU;AACZ,QAAA,aAA2C;AAEjD,IAAA,kBAAc;AAEwC;;;GAKrD;;IAGK,IAAA,aAAa;aACR;AAAA;;AAGb;;wCCxBA;;AAoBI,MAAA,sCAAS,sBAAsB,GAC/B,kCAAO,uBAAuB;wBAGU,iBAAiB,GAAzC,wCAAV,QAAQ;AACZ,MAAA,eAA2B,IAAI;AAEnC,IAAA,YAAc,MAAA;eACP,UAAU,EAAA;AACR,WAAA,EAAA,IAAA,UAAU,EAAC,sBAAqB;AAAA,MACrC,WAAS,QAAA;AAAA,MACT,OAAK,QAAA;AAAA,MACL,YAAY,WAAS,CAAG,QAAS,EAAA,IAAA,MAAO,KAAG,IAAA,EAAA;AAAA;GAE9C;;;;;;;;;;;;;;;;2BAOgB,IAAI,EAAC,OAAO,IAAC,QAAA,KAAA;AAAA,0BACd,IAAI,EAAC,OAAO,IAAC,QAAA,KAAA;AAAA,4BACX,IAAI,EAAC,KAAK,QAAK,QAAA,KAAA;AAAA,6BACd,IAAI,EAAC,KAAK,SAAM,QAAA,KAAA;AAAA,iCACN,OAAM,CAAA;AAAA,wBACf,KAAI;AAAA;;;;;;;gBATrB,IAAI,EAAA,UAAA,UAAA;AAAA;;;;AAFT;;yCCnCA;;MAUwC,YAAS,EAAA,WAAA,SAAA,CAAA,WAAA,YAAA,YAAA,YAAA,OAAA,CAAA;wBACf,QAAQ,GAAhC,wCAAA,UAAU;;;;eAIb,UAAU;AAAA,OACX;AAAA;;;;;;;;;;;;;;;AAJN;"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@embedpdf/plugin-zoom",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.4.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"main": "./dist/index.cjs",
|
|
@@ -26,31 +26,38 @@
|
|
|
26
26
|
"types": "./dist/vue/index.d.ts",
|
|
27
27
|
"import": "./dist/vue/index.js",
|
|
28
28
|
"require": "./dist/vue/index.cjs"
|
|
29
|
+
},
|
|
30
|
+
"./svelte": {
|
|
31
|
+
"types": "./dist/svelte/index.d.ts",
|
|
32
|
+
"svelte": "./dist/svelte/index.js",
|
|
33
|
+
"import": "./dist/svelte/index.js",
|
|
34
|
+
"require": "./dist/svelte/index.cjs"
|
|
29
35
|
}
|
|
30
36
|
},
|
|
31
37
|
"dependencies": {
|
|
32
38
|
"hammerjs": "^2.0.8",
|
|
33
|
-
"@embedpdf/models": "1.
|
|
39
|
+
"@embedpdf/models": "1.4.0"
|
|
34
40
|
},
|
|
35
41
|
"devDependencies": {
|
|
36
42
|
"@types/hammerjs": "^2.0.46",
|
|
37
43
|
"@types/react": "^18.2.0",
|
|
38
44
|
"typescript": "^5.0.0",
|
|
39
|
-
"@embedpdf/
|
|
40
|
-
"@embedpdf/
|
|
41
|
-
"@embedpdf/plugin-viewport": "1.
|
|
42
|
-
"@embedpdf/plugin-
|
|
43
|
-
"@embedpdf/plugin-
|
|
45
|
+
"@embedpdf/core": "1.4.0",
|
|
46
|
+
"@embedpdf/build": "1.1.0",
|
|
47
|
+
"@embedpdf/plugin-viewport": "1.4.0",
|
|
48
|
+
"@embedpdf/plugin-scroll": "1.4.0",
|
|
49
|
+
"@embedpdf/plugin-interaction-manager": "1.4.0"
|
|
44
50
|
},
|
|
45
51
|
"peerDependencies": {
|
|
46
52
|
"react": ">=16.8.0",
|
|
47
53
|
"react-dom": ">=16.8.0",
|
|
48
54
|
"preact": "^10.26.4",
|
|
49
55
|
"vue": ">=3.2.0",
|
|
50
|
-
"
|
|
51
|
-
"@embedpdf/
|
|
52
|
-
"@embedpdf/plugin-
|
|
53
|
-
"@embedpdf/plugin-
|
|
56
|
+
"svelte": ">=5 <6",
|
|
57
|
+
"@embedpdf/core": "1.4.0",
|
|
58
|
+
"@embedpdf/plugin-viewport": "1.4.0",
|
|
59
|
+
"@embedpdf/plugin-scroll": "1.4.0",
|
|
60
|
+
"@embedpdf/plugin-interaction-manager": "1.4.0"
|
|
54
61
|
},
|
|
55
62
|
"files": [
|
|
56
63
|
"dist",
|
|
@@ -73,7 +80,8 @@
|
|
|
73
80
|
"build:react": "vite build --mode react",
|
|
74
81
|
"build:preact": "vite build --mode preact",
|
|
75
82
|
"build:vue": "vite build --mode vue",
|
|
76
|
-
"build": "
|
|
83
|
+
"build:svelte": "vite build --mode svelte",
|
|
84
|
+
"build": "pnpm run clean && concurrently -c auto -n base,react,preact,vue,svelte \"vite build --mode base\" \"vite build --mode react\" \"vite build --mode preact\" \"vite build --mode vue\" \"vite build --mode svelte\"",
|
|
77
85
|
"clean": "rimraf dist",
|
|
78
86
|
"lint": "eslint src --color",
|
|
79
87
|
"lint:fix": "eslint src --color --fix"
|