@embedpdf/plugin-zoom 1.4.0 → 1.4.1

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.
@@ -1,3 +1,3 @@
1
1
  export declare function usePinch(): {
2
- readonly elementRef: HTMLDivElement | null;
2
+ elementRef: HTMLDivElement | null;
3
3
  };
@@ -10,6 +10,6 @@ export declare const useZoomPlugin: () => {
10
10
  ready: Promise<void>;
11
11
  };
12
12
  export declare const useZoom: () => {
13
- readonly state: ZoomState;
14
13
  readonly provides: Readonly<import('../../lib/index.ts').ZoomCapability> | null;
14
+ state: ZoomState;
15
15
  };
@@ -1,2 +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]})}));
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("svelte/internal/client"),t=require("@embedpdf/plugin-zoom"),o=require("@embedpdf/core/svelte");function r(e){const t=Object.create(null,{[Symbol.toStringTag]:{value:"Module"}});if(e)for(const o in e)if("default"!==o){const r=Object.getOwnPropertyDescriptor(e,o);Object.defineProperty(t,o,r.get?r:{enumerable:!0,get:()=>e[o]})}return t.default=e,Object.freeze(t)}require("svelte/internal/disclose-version");const n=r(e),s=()=>o.useCapability(t.ZoomPlugin.id);function i({element:e,viewportProvides:t,zoomProvides:o}){if("undefined"==typeof window)return()=>{};let r,n=0,s={x:0,y:0};const i=()=>{e.style.transform="none",e.style.transformOrigin="0 0"},l=r=>{var i;n=o.getState().currentZoomLevel;const l=t.getBoundingRect();s={x:r.center.x-l.origin.x,y:r.center.y-l.origin.y};const a=e.getBoundingClientRect();e.style.transformOrigin=`${r.center.x-a.left}px ${r.center.y-a.top}px`,(null==(i=r.srcEvent)?void 0:i.cancelable)&&(r.srcEvent.preventDefault(),r.srcEvent.stopPropagation())},a=t=>{var o,r;r=t.scale,e.style.transform=`scale(${r})`,(null==(o=t.srcEvent)?void 0:o.cancelable)&&(t.srcEvent.preventDefault(),t.srcEvent.stopPropagation())},c=e=>{const t=(e.scale-1)*n;o.requestZoomBy(t,{vx:s.x,vy:s.y}),i(),n=0};return(async()=>{try{const t=(await Promise.resolve().then((()=>require("../hammer-Bs-QCG8V.cjs"))).then((e=>e.hammer))).default,o=(()=>{const e="ontouchstart"in window||navigator.maxTouchPoints>0;return e&&/mobile|tablet|ip(ad|hone|od)|android/i.test(navigator.userAgent)?t.TouchInput:e?t.TouchMouseInput:t.MouseInput})();r=new t(e,{touchAction:"pan-x pan-y",inputClass:o}),r.get("pinch").set({enable:!0,pointers:2,threshold:.1}),r.on("pinchstart",l),r.on("pinchmove",a),r.on("pinchend",c)}catch(t){console.warn("Failed to load HammerJS:",t)}})(),()=>{null==r||r.destroy(),i()}}function l(){const e=o.useCapability("viewport"),t=s(),r=n.proxy({elementRef:null});return n.user_effect((()=>{const o=r.elementRef;if(o&&e.provides&&t.provides)return i({element:o,viewportProvides:e.provides,zoomProvides:t.provides})})),r}var a=n.from_html("<div></div>");var c=n.from_html("<div> </div>");exports.MarqueeZoom=function(e,t){n.push(t,!0);let o=n.prop(t,"stroke",3,"rgba(33,150,243,0.8)"),r=n.prop(t,"fill",3,"rgba(33,150,243,0.15)");const i=s();let l=n.state(null);n.user_effect((()=>{if(i.provides)return i.provides.registerMarqueeOnPage({pageIndex:t.pageIndex,scale:t.scale,callback:{onPreview:e=>n.set(l,e,!0)}})}));var c=n.comment(),p=n.first_child(c),u=e=>{var s=a();let i;n.template_effect((e=>{n.set_class(s,1,n.clsx(t.class)),i=n.set_style(s,"",i,e)}),[()=>({position:"absolute","pointer-events":"none",left:n.get(l).origin.x*t.scale+"px",top:n.get(l).origin.y*t.scale+"px",width:n.get(l).size.width*t.scale+"px",height:n.get(l).size.height*t.scale+"px",border:`1px solid ${o()}`,background:r(),"box-sizing":"border-box"})]),n.append(e,s)};n.if(p,(e=>{n.get(l)&&e(u)})),n.append(e,c),n.pop()},exports.PinchWrapper=function(e,t){n.push(t,!0);let o=n.rest_props(t,["$$slots","$$events","$$legacy","children","class"]);const r=l();var s=c();n.attribute_effect(s,(()=>({...o,class:t.class,[n.STYLE]:{display:"block",width:"fit-content",overflow:"visible","box-sizing":"border-box",margin:"0px auto"}})));var i=n.child(s,!0);n.reset(s),n.bind_this(s,(e=>r.elementRef=e),(()=>null==r?void 0:r.elementRef)),n.template_effect((()=>n.set_text(i,t.children))),n.append(e,s),n.pop()},exports.usePinch=l,exports.useZoom=()=>{const e=s(),o=n.proxy({get provides(){return e.provides},state:t.initialState});return n.user_effect((()=>{if(e.provides)return e.provides.onStateChange((e=>{o.state=e}))})),o},exports.useZoomCapability=s,exports.useZoomPlugin=()=>o.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
2
  //# sourceMappingURL=index.cjs.map
@@ -1 +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"}
1
+ {"version":3,"file":"index.cjs","sources":["../../src/svelte/hooks/use-zoom.svelte.ts","../../src/shared/utils/pinch-zoom-logic.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 capability = useZoomCapability();\n\n const state = $state({\n get provides() {\n return capability.provides;\n },\n state: initialState as ZoomState,\n });\n\n $effect(() => {\n if (!capability.provides) return;\n return capability.provides.onStateChange((newState) => {\n state.state = newState;\n });\n });\n\n return state;\n};\n","import type { ViewportCapability } from '@embedpdf/plugin-viewport';\nimport type { ZoomCapability, ZoomState } from '@embedpdf/plugin-zoom';\n\nexport interface PinchZoomDeps {\n element: HTMLDivElement;\n viewportProvides: ViewportCapability;\n zoomProvides: ZoomCapability;\n}\n\nexport function setupPinchZoom({ element, viewportProvides, zoomProvides }: PinchZoomDeps) {\n // Check if we're on the client side\n if (typeof window === 'undefined') {\n return () => {};\n }\n\n let hammer: any | undefined;\n let initialZoom = 0; // numeric scale at pinchstart\n let lastCenter = { x: 0, y: 0 };\n\n const getState = (): ZoomState => zoomProvides.getState();\n\n const updateTransform = (scale: number) => {\n // 1 → no scale; we only scale *relatively* to the start\n element.style.transform = `scale(${scale})`;\n };\n\n const resetTransform = () => {\n element.style.transform = 'none';\n element.style.transformOrigin = '0 0';\n };\n\n const pinchStart = (e: HammerInput) => {\n initialZoom = getState().currentZoomLevel;\n\n const contRect = viewportProvides.getBoundingRect();\n\n lastCenter = {\n x: e.center.x - contRect.origin.x,\n y: e.center.y - contRect.origin.y,\n };\n\n // put the transform-origin under the fingers so the preview feels right\n const innerRect = element.getBoundingClientRect();\n element.style.transformOrigin = `${e.center.x - innerRect.left}px ${e.center.y - innerRect.top}px`;\n\n // stop the browser's own pinch-zoom\n if (e.srcEvent?.cancelable) {\n e.srcEvent.preventDefault();\n e.srcEvent.stopPropagation();\n }\n };\n\n const pinchMove = (e: HammerInput) => {\n updateTransform(e.scale); // *only* CSS, no real zoom yet\n if (e.srcEvent?.cancelable) {\n e.srcEvent.preventDefault();\n e.srcEvent.stopPropagation();\n }\n };\n\n const pinchEnd = (e: HammerInput) => {\n // translate the relative hammer scale into a delta for requestZoomBy\n const delta = (e.scale - 1) * initialZoom;\n zoomProvides.requestZoomBy(delta, { vx: lastCenter.x, vy: lastCenter.y });\n\n resetTransform();\n initialZoom = 0;\n };\n\n // Async Hammer setup (internal)\n const setupHammer = async () => {\n try {\n const Hammer = (await import('hammerjs')).default;\n\n /* ------------------------------------------------------------------ */\n /* Hammer setup */\n /* ------------------------------------------------------------------ */\n const inputClass = (() => {\n const MOBILE_REGEX = /mobile|tablet|ip(ad|hone|od)|android/i;\n const SUPPORT_TOUCH = 'ontouchstart' in window || navigator.maxTouchPoints > 0;\n const SUPPORT_ONLY_TOUCH = SUPPORT_TOUCH && MOBILE_REGEX.test(navigator.userAgent);\n if (SUPPORT_ONLY_TOUCH) return Hammer.TouchInput;\n if (!SUPPORT_TOUCH) return Hammer.MouseInput;\n return Hammer.TouchMouseInput;\n })();\n\n hammer = new Hammer(element, {\n touchAction: 'pan-x pan-y', // allow scroll in every direction\n inputClass,\n });\n\n hammer.get('pinch').set({ enable: true, pointers: 2, threshold: 0.1 });\n\n hammer.on('pinchstart', pinchStart);\n hammer.on('pinchmove', pinchMove);\n hammer.on('pinchend', pinchEnd);\n } catch (error) {\n console.warn('Failed to load HammerJS:', error);\n }\n };\n\n setupHammer(); // Fire and forget\n\n // Return cleanup immediately\n return () => {\n hammer?.destroy();\n resetTransform();\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 viewportCapability = useCapability<ViewportPlugin>('viewport');\n const zoomCapability = useZoomCapability();\n\n const state = $state({\n elementRef: null as HTMLDivElement | null,\n });\n\n $effect(() => {\n const element = state.elementRef;\n if (!element || !viewportCapability.provides || !zoomCapability.provides) {\n return;\n }\n\n return setupPinchZoom({\n element,\n viewportProvides: viewportCapability.provides,\n zoomProvides: zoomCapability.provides,\n });\n });\n\n return state;\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 zoomCapability = useZoomCapability();\n let rect = $state<Rect | null>(null);\n\n $effect(() => {\n if (!zoomCapability.provides) return;\n return zoomCapability.provides.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 pinch = usePinch();\n</script>\n\n<div\n bind:this={pinch.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"],"names":["useZoomCapability","useCapability","ZoomPlugin","id","setupPinchZoom","element","viewportProvides","zoomProvides","window","hammer","initialZoom","lastCenter","x","y","resetTransform","style","transform","transformOrigin","pinchStart","e","getState","currentZoomLevel","contRect","getBoundingRect","center","origin","innerRect","getBoundingClientRect","left","top","_a","srcEvent","cancelable","preventDefault","stopPropagation","pinchMove","scale","pinchEnd","delta","requestZoomBy","vx","vy","async","Hammer","Promise","resolve","then","require","n","default","inputClass","SUPPORT_TOUCH","navigator","maxTouchPoints","test","userAgent","TouchInput","TouchMouseInput","MouseInput","touchAction","get","set","enable","pointers","threshold","on","error","console","warn","setupHammer","destroy","usePinch","viewportCapability","zoomCapability","state","elementRef","$","user_effect","provides","stroke","fill","rect","registerMarqueeOnPage","pageIndex","$$props","callback","onPreview","val","size","width","height","consequent","restProps","rest_props","pinch","$__namespace","bind_this","div","$$value","capability","initialState","onStateChange","newState","usePlugin"],"mappings":"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"}
@@ -6,49 +6,122 @@ import "svelte/internal/disclose-version";
6
6
  const useZoomCapability = () => useCapability(ZoomPlugin.id);
7
7
  const useZoomPlugin = () => usePlugin(ZoomPlugin.id);
8
8
  const useZoom = () => {
9
- const $$d = $.derived(useZoomCapability), provides = $.derived(() => $.get($$d).provides);
10
- let zoomState = $.state($.proxy(initialState));
9
+ const capability = useZoomCapability();
10
+ const state = $.proxy({
11
+ get provides() {
12
+ return capability.provides;
13
+ },
14
+ state: initialState
15
+ });
11
16
  $.user_effect(() => {
12
- var _a;
13
- return (_a = $.get(provides)) == null ? void 0 : _a.onStateChange((action) => {
14
- $.set(zoomState, action, true);
17
+ if (!capability.provides) return;
18
+ return capability.provides.onStateChange((newState) => {
19
+ state.state = newState;
15
20
  });
16
21
  });
17
- return {
18
- get state() {
19
- return $.get(zoomState);
20
- },
21
- get provides() {
22
- return $.get(provides);
22
+ return state;
23
+ };
24
+ function setupPinchZoom({ element, viewportProvides, zoomProvides }) {
25
+ if (typeof window === "undefined") {
26
+ return () => {
27
+ };
28
+ }
29
+ let hammer;
30
+ let initialZoom = 0;
31
+ let lastCenter = { x: 0, y: 0 };
32
+ const getState = () => zoomProvides.getState();
33
+ const updateTransform = (scale) => {
34
+ element.style.transform = `scale(${scale})`;
35
+ };
36
+ const resetTransform = () => {
37
+ element.style.transform = "none";
38
+ element.style.transformOrigin = "0 0";
39
+ };
40
+ const pinchStart = (e) => {
41
+ var _a;
42
+ initialZoom = getState().currentZoomLevel;
43
+ const contRect = viewportProvides.getBoundingRect();
44
+ lastCenter = {
45
+ x: e.center.x - contRect.origin.x,
46
+ y: e.center.y - contRect.origin.y
47
+ };
48
+ const innerRect = element.getBoundingClientRect();
49
+ element.style.transformOrigin = `${e.center.x - innerRect.left}px ${e.center.y - innerRect.top}px`;
50
+ if ((_a = e.srcEvent) == null ? void 0 : _a.cancelable) {
51
+ e.srcEvent.preventDefault();
52
+ e.srcEvent.stopPropagation();
23
53
  }
24
54
  };
25
- };
55
+ const pinchMove = (e) => {
56
+ var _a;
57
+ updateTransform(e.scale);
58
+ if ((_a = e.srcEvent) == null ? void 0 : _a.cancelable) {
59
+ e.srcEvent.preventDefault();
60
+ e.srcEvent.stopPropagation();
61
+ }
62
+ };
63
+ const pinchEnd = (e) => {
64
+ const delta = (e.scale - 1) * initialZoom;
65
+ zoomProvides.requestZoomBy(delta, { vx: lastCenter.x, vy: lastCenter.y });
66
+ resetTransform();
67
+ initialZoom = 0;
68
+ };
69
+ const setupHammer = async () => {
70
+ try {
71
+ const Hammer = (await import("../hammer-e1aXHboh.js").then((n) => n.h)).default;
72
+ const inputClass = (() => {
73
+ const MOBILE_REGEX = /mobile|tablet|ip(ad|hone|od)|android/i;
74
+ const SUPPORT_TOUCH = "ontouchstart" in window || navigator.maxTouchPoints > 0;
75
+ const SUPPORT_ONLY_TOUCH = SUPPORT_TOUCH && MOBILE_REGEX.test(navigator.userAgent);
76
+ if (SUPPORT_ONLY_TOUCH) return Hammer.TouchInput;
77
+ if (!SUPPORT_TOUCH) return Hammer.MouseInput;
78
+ return Hammer.TouchMouseInput;
79
+ })();
80
+ hammer = new Hammer(element, {
81
+ touchAction: "pan-x pan-y",
82
+ // allow scroll in every direction
83
+ inputClass
84
+ });
85
+ hammer.get("pinch").set({ enable: true, pointers: 2, threshold: 0.1 });
86
+ hammer.on("pinchstart", pinchStart);
87
+ hammer.on("pinchmove", pinchMove);
88
+ hammer.on("pinchend", pinchEnd);
89
+ } catch (error) {
90
+ console.warn("Failed to load HammerJS:", error);
91
+ }
92
+ };
93
+ setupHammer();
94
+ return () => {
95
+ hammer == null ? void 0 : hammer.destroy();
96
+ resetTransform();
97
+ };
98
+ }
26
99
  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;
100
+ const viewportCapability = useCapability("viewport");
101
+ const zoomCapability = useZoomCapability();
102
+ const state = $.proxy({ elementRef: null });
32
103
  $.user_effect(() => {
33
- {
104
+ const element = state.elementRef;
105
+ if (!element || !viewportCapability.provides || !zoomCapability.provides) {
34
106
  return;
35
107
  }
108
+ return setupPinchZoom({
109
+ element,
110
+ viewportProvides: viewportCapability.provides,
111
+ zoomProvides: zoomCapability.provides
112
+ });
36
113
  });
37
- return {
38
- get elementRef() {
39
- return elementRef;
40
- }
41
- };
114
+ return state;
42
115
  }
43
116
  var root_1 = $.from_html(`<div></div>`);
44
117
  function MarqueeZoom($$anchor, $$props) {
45
118
  $.push($$props, true);
46
119
  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);
120
+ const zoomCapability = useZoomCapability();
48
121
  let rect = $.state(null);
49
122
  $.user_effect(() => {
50
- if (!$.get(zoomPlugin)) return;
51
- return $.get(zoomPlugin).registerMarqueeOnPage({
123
+ if (!zoomCapability.provides) return;
124
+ return zoomCapability.provides.registerMarqueeOnPage({
52
125
  pageIndex: $$props.pageIndex,
53
126
  scale: $$props.scale,
54
127
  callback: { onPreview: (val) => $.set(rect, val, true) }
@@ -88,15 +161,13 @@ function MarqueeZoom($$anchor, $$props) {
88
161
  $.append($$anchor, fragment);
89
162
  $.pop();
90
163
  }
91
- var root = $.from_html(`<div> </div> }`, 1);
164
+ var root = $.from_html(`<div> </div>`);
92
165
  function PinchWrapper($$anchor, $$props) {
93
166
  $.push($$props, true);
94
167
  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);
168
+ const pinch = usePinch();
169
+ var div = root();
98
170
  $.attribute_effect(div, () => ({
99
- ref: $.get(elementRef),
100
171
  ...restProps,
101
172
  class: $$props.class,
102
173
  [$.STYLE]: {
@@ -109,9 +180,9 @@ function PinchWrapper($$anchor, $$props) {
109
180
  }));
110
181
  var text = $.child(div, true);
111
182
  $.reset(div);
112
- $.next();
183
+ $.bind_this(div, ($$value) => pinch.elementRef = $$value, () => pinch == null ? void 0 : pinch.elementRef);
113
184
  $.template_effect(() => $.set_text(text, $$props.children));
114
- $.append($$anchor, fragment);
185
+ $.append($$anchor, div);
115
186
  $.pop();
116
187
  }
117
188
  export {
@@ -1 +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;"}
1
+ {"version":3,"file":"index.js","sources":["../../src/svelte/hooks/use-zoom.svelte.ts","../../src/shared/utils/pinch-zoom-logic.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 capability = useZoomCapability();\n\n const state = $state({\n get provides() {\n return capability.provides;\n },\n state: initialState as ZoomState,\n });\n\n $effect(() => {\n if (!capability.provides) return;\n return capability.provides.onStateChange((newState) => {\n state.state = newState;\n });\n });\n\n return state;\n};\n","import type { ViewportCapability } from '@embedpdf/plugin-viewport';\nimport type { ZoomCapability, ZoomState } from '@embedpdf/plugin-zoom';\n\nexport interface PinchZoomDeps {\n element: HTMLDivElement;\n viewportProvides: ViewportCapability;\n zoomProvides: ZoomCapability;\n}\n\nexport function setupPinchZoom({ element, viewportProvides, zoomProvides }: PinchZoomDeps) {\n // Check if we're on the client side\n if (typeof window === 'undefined') {\n return () => {};\n }\n\n let hammer: any | undefined;\n let initialZoom = 0; // numeric scale at pinchstart\n let lastCenter = { x: 0, y: 0 };\n\n const getState = (): ZoomState => zoomProvides.getState();\n\n const updateTransform = (scale: number) => {\n // 1 → no scale; we only scale *relatively* to the start\n element.style.transform = `scale(${scale})`;\n };\n\n const resetTransform = () => {\n element.style.transform = 'none';\n element.style.transformOrigin = '0 0';\n };\n\n const pinchStart = (e: HammerInput) => {\n initialZoom = getState().currentZoomLevel;\n\n const contRect = viewportProvides.getBoundingRect();\n\n lastCenter = {\n x: e.center.x - contRect.origin.x,\n y: e.center.y - contRect.origin.y,\n };\n\n // put the transform-origin under the fingers so the preview feels right\n const innerRect = element.getBoundingClientRect();\n element.style.transformOrigin = `${e.center.x - innerRect.left}px ${e.center.y - innerRect.top}px`;\n\n // stop the browser's own pinch-zoom\n if (e.srcEvent?.cancelable) {\n e.srcEvent.preventDefault();\n e.srcEvent.stopPropagation();\n }\n };\n\n const pinchMove = (e: HammerInput) => {\n updateTransform(e.scale); // *only* CSS, no real zoom yet\n if (e.srcEvent?.cancelable) {\n e.srcEvent.preventDefault();\n e.srcEvent.stopPropagation();\n }\n };\n\n const pinchEnd = (e: HammerInput) => {\n // translate the relative hammer scale into a delta for requestZoomBy\n const delta = (e.scale - 1) * initialZoom;\n zoomProvides.requestZoomBy(delta, { vx: lastCenter.x, vy: lastCenter.y });\n\n resetTransform();\n initialZoom = 0;\n };\n\n // Async Hammer setup (internal)\n const setupHammer = async () => {\n try {\n const Hammer = (await import('hammerjs')).default;\n\n /* ------------------------------------------------------------------ */\n /* Hammer setup */\n /* ------------------------------------------------------------------ */\n const inputClass = (() => {\n const MOBILE_REGEX = /mobile|tablet|ip(ad|hone|od)|android/i;\n const SUPPORT_TOUCH = 'ontouchstart' in window || navigator.maxTouchPoints > 0;\n const SUPPORT_ONLY_TOUCH = SUPPORT_TOUCH && MOBILE_REGEX.test(navigator.userAgent);\n if (SUPPORT_ONLY_TOUCH) return Hammer.TouchInput;\n if (!SUPPORT_TOUCH) return Hammer.MouseInput;\n return Hammer.TouchMouseInput;\n })();\n\n hammer = new Hammer(element, {\n touchAction: 'pan-x pan-y', // allow scroll in every direction\n inputClass,\n });\n\n hammer.get('pinch').set({ enable: true, pointers: 2, threshold: 0.1 });\n\n hammer.on('pinchstart', pinchStart);\n hammer.on('pinchmove', pinchMove);\n hammer.on('pinchend', pinchEnd);\n } catch (error) {\n console.warn('Failed to load HammerJS:', error);\n }\n };\n\n setupHammer(); // Fire and forget\n\n // Return cleanup immediately\n return () => {\n hammer?.destroy();\n resetTransform();\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 viewportCapability = useCapability<ViewportPlugin>('viewport');\n const zoomCapability = useZoomCapability();\n\n const state = $state({\n elementRef: null as HTMLDivElement | null,\n });\n\n $effect(() => {\n const element = state.elementRef;\n if (!element || !viewportCapability.provides || !zoomCapability.provides) {\n return;\n }\n\n return setupPinchZoom({\n element,\n viewportProvides: viewportCapability.provides,\n zoomProvides: zoomCapability.provides,\n });\n });\n\n return state;\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 zoomCapability = useZoomCapability();\n let rect = $state<Rect | null>(null);\n\n $effect(() => {\n if (!zoomCapability.provides) return;\n return zoomCapability.provides.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 pinch = usePinch();\n</script>\n\n<div\n bind:this={pinch.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"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@embedpdf/plugin-zoom",
3
- "version": "1.4.0",
3
+ "version": "1.4.1",
4
4
  "type": "module",
5
5
  "license": "MIT",
6
6
  "main": "./dist/index.cjs",
@@ -36,17 +36,17 @@
36
36
  },
37
37
  "dependencies": {
38
38
  "hammerjs": "^2.0.8",
39
- "@embedpdf/models": "1.4.0"
39
+ "@embedpdf/models": "1.4.1"
40
40
  },
41
41
  "devDependencies": {
42
42
  "@types/hammerjs": "^2.0.46",
43
43
  "@types/react": "^18.2.0",
44
44
  "typescript": "^5.0.0",
45
- "@embedpdf/core": "1.4.0",
45
+ "@embedpdf/core": "1.4.1",
46
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"
47
+ "@embedpdf/plugin-viewport": "1.4.1",
48
+ "@embedpdf/plugin-scroll": "1.4.1",
49
+ "@embedpdf/plugin-interaction-manager": "1.4.1"
50
50
  },
51
51
  "peerDependencies": {
52
52
  "react": ">=16.8.0",
@@ -54,10 +54,10 @@
54
54
  "preact": "^10.26.4",
55
55
  "vue": ">=3.2.0",
56
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"
57
+ "@embedpdf/core": "1.4.1",
58
+ "@embedpdf/plugin-viewport": "1.4.1",
59
+ "@embedpdf/plugin-scroll": "1.4.1",
60
+ "@embedpdf/plugin-interaction-manager": "1.4.1"
61
61
  },
62
62
  "files": [
63
63
  "dist",