@embedpdf/plugin-zoom 1.0.20 → 1.0.21
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/preact/index.cjs +1 -1
- package/dist/preact/index.cjs.map +1 -1
- package/dist/preact/index.js +77 -72
- package/dist/preact/index.js.map +1 -1
- package/dist/react/index.cjs +1 -1
- package/dist/react/index.cjs.map +1 -1
- package/dist/react/index.js +77 -72
- package/dist/react/index.js.map +1 -1
- package/dist/shared-preact/index.d.ts +1 -0
- package/dist/shared-preact/utils/pinch-zoom-logic.d.ts +8 -0
- package/dist/shared-react/index.d.ts +1 -0
- package/dist/shared-react/utils/pinch-zoom-logic.d.ts +8 -0
- package/dist/shared-vue/utils/pinch-zoom-logic.d.ts +8 -0
- package/dist/vue/components/index.d.ts +2 -0
- package/dist/vue/components/marquee-zoom.vue.d.ts +16 -0
- package/dist/vue/components/pinch-wrapper.vue.d.ts +12 -0
- package/dist/vue/hooks/index.d.ts +2 -0
- package/dist/vue/hooks/use-pinch-zoom.d.ts +3 -0
- package/dist/vue/hooks/use-zoom.d.ts +13 -0
- package/dist/vue/index.cjs +2 -0
- package/dist/vue/index.cjs.map +1 -0
- package/dist/vue/index.d.ts +3 -0
- package/dist/vue/index.js +197 -0
- package/dist/vue/index.js.map +1 -0
- package/package.json +18 -11
- package/dist/preact/interaction-manager.d.ts +0 -1
- package/dist/react/interaction-manager.d.ts +0 -1
package/dist/preact/index.cjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("@embedpdf/core/preact"),t=require("@embedpdf/plugin-zoom");require("preact");const
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("@embedpdf/core/preact"),t=require("@embedpdf/plugin-zoom");require("preact");const o=require("preact/hooks"),n=require("preact/jsx-runtime"),r=()=>e.useCapability(t.ZoomPlugin.id);function i({element:e,viewportProvides:t,zoomProvides:o}){if("undefined"==typeof window)return()=>{};let n,r=0,i={x:0,y:0};const s=()=>{e.style.transform="none",e.style.transformOrigin="0 0"},a=n=>{var s;r=o.getState().currentZoomLevel;const a=t.getBoundingRect();i={x:n.center.x-a.origin.x,y:n.center.y-a.origin.y};const l=e.getBoundingClientRect();e.style.transformOrigin=`${n.center.x-l.left}px ${n.center.y-l.top}px`,(null==(s=n.srcEvent)?void 0:s.cancelable)&&(n.srcEvent.preventDefault(),n.srcEvent.stopPropagation())},l=t=>{var o,n;n=t.scale,e.style.transform=`scale(${n})`,(null==(o=t.srcEvent)?void 0:o.cancelable)&&(t.srcEvent.preventDefault(),t.srcEvent.stopPropagation())},c=e=>{const t=(e.scale-1)*r;o.requestZoomBy(t,{vx:i.x,vy:i.y}),s(),r=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})();n=new t(e,{touchAction:"pan-x pan-y",inputClass:o}),n.get("pinch").set({enable:!0,pointers:2,threshold:.1}),n.on("pinchstart",a),n.on("pinchmove",l),n.on("pinchend",c)}catch(t){console.warn("Failed to load HammerJS:",t)}})(),()=>{null==n||n.destroy(),s()}}function s(){const{provides:t}=e.useCapability("viewport"),{provides:n}=r(),s=o.useRef(null);return o.useEffect((()=>{const e=s.current;if(e&&t&&n)return i({element:e,viewportProvides:t,zoomProvides:n})}),[t,n]),{elementRef:s}}exports.MarqueeZoom=({pageIndex:e,scale:t,className:i,stroke:s="rgba(33,150,243,0.8)",fill:a="rgba(33,150,243,0.15)"})=>{const{provides:l}=r(),[c,u]=o.useState(null);return o.useEffect((()=>{if(l)return l.registerMarqueeOnPage({pageIndex:e,scale:t,callback:{onPreview:u}})}),[l,e,t]),c?n.jsx("div",{style:{position:"absolute",pointerEvents:"none",left:c.origin.x*t,top:c.origin.y*t,width:c.size.width*t,height:c.size.height*t,border:`1px solid ${s}`,background:a,boxSizing:"border-box"},className:i}):null},exports.PinchWrapper=function({children:e,style:t,...o}){const{elementRef:r}=s();return n.jsx("div",{ref:r,...o,style:{...t,display:"block",width:"fit-content",overflow:"visible",boxSizing:"border-box",margin:"0px auto"},children:e})},exports.usePinch=s,exports.useZoom=()=>{const{provides:e}=r(),[n,i]=o.useState(t.initialState);return o.useEffect((()=>null==e?void 0:e.onStateChange((e=>{i(e)}))),[e]),{state:n,provides:e}},exports.useZoomCapability=r,exports.useZoomPlugin=()=>e.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/shared/hooks/use-zoom.ts","../../src/shared/hooks/use-pinch-zoom.ts","../../src/shared/components/marquee-zoom.tsx","../../src/shared/components/pinch-wrapper.tsx"],"sourcesContent":["import { useCapability, usePlugin } from '@embedpdf/core/@framework';\nimport { initialState, ZoomPlugin, ZoomState } from '@embedpdf/plugin-zoom';\nimport { useEffect, useState } from '@framework';\n\nexport const useZoomCapability = () => useCapability<ZoomPlugin>(ZoomPlugin.id);\nexport const useZoomPlugin = () => usePlugin<ZoomPlugin>(ZoomPlugin.id);\n\nexport const useZoom = () => {\n const { provides } = useZoomCapability();\n const [state, setState] = useState<ZoomState>(initialState);\n\n useEffect(() => {\n return provides?.onStateChange((action) => {\n setState(action);\n });\n }, [provides]);\n\n return {\n state,\n provides,\n };\n};\n","import { useEffect, useRef } from '@framework';\nimport { useCapability } from '@embedpdf/core/@framework';\nimport { ViewportPlugin } from '@embedpdf/plugin-viewport';\nimport { ZoomState } from '@embedpdf/plugin-zoom';\n\nimport { useZoomCapability } from './use-zoom';\n\nexport function usePinch() {\n const { provides: viewportProvides } = useCapability<ViewportPlugin>('viewport');\n const { provides: zoomProvides } = useZoomCapability();\n const elementRef = useRef<HTMLDivElement>(null);\n\n useEffect(() => {\n const element = elementRef.current;\n if (!element || !viewportProvides || !zoomProvides) {\n return;\n }\n\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 // Dynamically import and setup Hammer\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();\n\n return () => {\n hammer?.destroy();\n resetTransform();\n };\n }, [viewportProvides, zoomProvides]);\n\n return { elementRef };\n}\n","import { useEffect, useState } from '@framework';\nimport { Rect } from '@embedpdf/models';\n\nimport { useZoomCapability } from '../hooks/use-zoom';\n\ninterface 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 className?: string;\n /** Stroke / fill colours (defaults below) */\n stroke?: string;\n fill?: string;\n}\n\nexport const MarqueeZoom = ({\n pageIndex,\n scale,\n className,\n stroke = 'rgba(33,150,243,0.8)',\n fill = 'rgba(33,150,243,0.15)',\n}: MarqueeZoomProps) => {\n const { provides: zoomPlugin } = useZoomCapability();\n const [rect, setRect] = useState<Rect | null>(null);\n\n useEffect(() => {\n if (!zoomPlugin) return;\n return zoomPlugin.registerMarqueeOnPage({\n pageIndex,\n scale,\n callback: {\n onPreview: setRect,\n },\n });\n }, [zoomPlugin, pageIndex, scale]);\n\n if (!rect) return null;\n\n return (\n <div\n style={{\n position: 'absolute',\n pointerEvents: 'none',\n left: rect.origin.x * scale,\n top: rect.origin.y * scale,\n width: rect.size.width * scale,\n height: rect.size.height * scale,\n border: `1px solid ${stroke}`,\n background: fill,\n boxSizing: 'border-box',\n }}\n className={className}\n />\n );\n};\n","import { ReactNode, HTMLAttributes, CSSProperties } from '@framework';\n\nimport { usePinch } from '../hooks';\n\ntype PinchWrapperProps = Omit<HTMLAttributes<HTMLDivElement>, 'style'> & {\n children: ReactNode;\n style?: CSSProperties;\n};\n\nexport function PinchWrapper({ children, style, ...props }: PinchWrapperProps) {\n const { elementRef } = usePinch();\n\n return (\n <div\n ref={elementRef}\n {...props}\n style={{\n ...style,\n display: 'block',\n width: 'fit-content',\n overflow: 'visible',\n boxSizing: 'border-box',\n margin: '0px auto',\n }}\n >\n {children}\n </div>\n );\n}\n"],"names":["useZoomCapability","useCapability","ZoomPlugin","id","usePinch","provides","viewportProvides","zoomProvides","elementRef","useRef","useEffect","element","current","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","pageIndex","className","stroke","fill","zoomPlugin","rect","setRect","useState","registerMarqueeOnPage","callback","onPreview","jsxRuntime","jsx","position","pointerEvents","width","size","height","border","background","boxSizing","children","props","ref","display","overflow","margin","state","setState","initialState","onStateChange","action","usePlugin"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.cjs","sources":["../../src/shared/hooks/use-zoom.ts","../../src/shared/utils/pinch-zoom-logic.ts","../../src/shared/hooks/use-pinch-zoom.ts","../../src/shared/components/marquee-zoom.tsx","../../src/shared/components/pinch-wrapper.tsx"],"sourcesContent":["import { useCapability, usePlugin } from '@embedpdf/core/@framework';\nimport { initialState, ZoomPlugin, ZoomState } from '@embedpdf/plugin-zoom';\nimport { useEffect, useState } from '@framework';\n\nexport const useZoomCapability = () => useCapability<ZoomPlugin>(ZoomPlugin.id);\nexport const useZoomPlugin = () => usePlugin<ZoomPlugin>(ZoomPlugin.id);\n\nexport const useZoom = () => {\n const { provides } = useZoomCapability();\n const [state, setState] = useState<ZoomState>(initialState);\n\n useEffect(() => {\n return provides?.onStateChange((action) => {\n setState(action);\n });\n }, [provides]);\n\n return {\n state,\n provides,\n };\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 { useEffect, useRef } from '@framework';\nimport { useCapability } from '@embedpdf/core/@framework';\nimport { ViewportPlugin } from '@embedpdf/plugin-viewport';\n\nimport { setupPinchZoom } from '../utils/pinch-zoom-logic';\nimport { useZoomCapability } from './use-zoom';\n\nexport function usePinch() {\n const { provides: viewportProvides } = useCapability<ViewportPlugin>('viewport');\n const { provides: zoomProvides } = useZoomCapability();\n const elementRef = useRef<HTMLDivElement>(null);\n\n useEffect(() => {\n const element = elementRef.current;\n if (!element || !viewportProvides || !zoomProvides) {\n return;\n }\n\n return setupPinchZoom({ element, viewportProvides, zoomProvides });\n }, [viewportProvides, zoomProvides]);\n\n return { elementRef };\n}\n","import { useEffect, useState } from '@framework';\nimport { Rect } from '@embedpdf/models';\n\nimport { useZoomCapability } from '../hooks/use-zoom';\n\ninterface 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 className?: string;\n /** Stroke / fill colours (defaults below) */\n stroke?: string;\n fill?: string;\n}\n\nexport const MarqueeZoom = ({\n pageIndex,\n scale,\n className,\n stroke = 'rgba(33,150,243,0.8)',\n fill = 'rgba(33,150,243,0.15)',\n}: MarqueeZoomProps) => {\n const { provides: zoomPlugin } = useZoomCapability();\n const [rect, setRect] = useState<Rect | null>(null);\n\n useEffect(() => {\n if (!zoomPlugin) return;\n return zoomPlugin.registerMarqueeOnPage({\n pageIndex,\n scale,\n callback: {\n onPreview: setRect,\n },\n });\n }, [zoomPlugin, pageIndex, scale]);\n\n if (!rect) return null;\n\n return (\n <div\n style={{\n position: 'absolute',\n pointerEvents: 'none',\n left: rect.origin.x * scale,\n top: rect.origin.y * scale,\n width: rect.size.width * scale,\n height: rect.size.height * scale,\n border: `1px solid ${stroke}`,\n background: fill,\n boxSizing: 'border-box',\n }}\n className={className}\n />\n );\n};\n","import { ReactNode, HTMLAttributes, CSSProperties } from '@framework';\n\nimport { usePinch } from '../hooks';\n\ntype PinchWrapperProps = Omit<HTMLAttributes<HTMLDivElement>, 'style'> & {\n children: ReactNode;\n style?: CSSProperties;\n};\n\nexport function PinchWrapper({ children, style, ...props }: PinchWrapperProps) {\n const { elementRef } = usePinch();\n\n return (\n <div\n ref={elementRef}\n {...props}\n style={{\n ...style,\n display: 'block',\n width: 'fit-content',\n overflow: 'visible',\n boxSizing: 'border-box',\n margin: '0px auto',\n }}\n >\n {children}\n </div>\n );\n}\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","provides","elementRef","useRef","useEffect","current","pageIndex","className","stroke","fill","zoomPlugin","rect","setRect","useState","registerMarqueeOnPage","callback","onPreview","jsxRuntime","jsx","position","pointerEvents","width","size","height","border","background","boxSizing","children","props","ref","display","overflow","margin","state","setState","initialState","onStateChange","action","usePlugin"],"mappings":"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"}
|
package/dist/preact/index.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { useCapability, usePlugin } from "@embedpdf/core/preact";
|
|
2
2
|
import { ZoomPlugin, initialState } from "@embedpdf/plugin-zoom";
|
|
3
|
+
export * from "@embedpdf/plugin-zoom";
|
|
3
4
|
import "preact";
|
|
4
5
|
import { useState, useEffect, useRef } from "preact/hooks";
|
|
5
6
|
import { jsx } from "preact/jsx-runtime";
|
|
@@ -18,6 +19,81 @@ const useZoom = () => {
|
|
|
18
19
|
provides
|
|
19
20
|
};
|
|
20
21
|
};
|
|
22
|
+
function setupPinchZoom({ element, viewportProvides, zoomProvides }) {
|
|
23
|
+
if (typeof window === "undefined") {
|
|
24
|
+
return () => {
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
let hammer;
|
|
28
|
+
let initialZoom = 0;
|
|
29
|
+
let lastCenter = { x: 0, y: 0 };
|
|
30
|
+
const getState = () => zoomProvides.getState();
|
|
31
|
+
const updateTransform = (scale) => {
|
|
32
|
+
element.style.transform = `scale(${scale})`;
|
|
33
|
+
};
|
|
34
|
+
const resetTransform = () => {
|
|
35
|
+
element.style.transform = "none";
|
|
36
|
+
element.style.transformOrigin = "0 0";
|
|
37
|
+
};
|
|
38
|
+
const pinchStart = (e) => {
|
|
39
|
+
var _a;
|
|
40
|
+
initialZoom = getState().currentZoomLevel;
|
|
41
|
+
const contRect = viewportProvides.getBoundingRect();
|
|
42
|
+
lastCenter = {
|
|
43
|
+
x: e.center.x - contRect.origin.x,
|
|
44
|
+
y: e.center.y - contRect.origin.y
|
|
45
|
+
};
|
|
46
|
+
const innerRect = element.getBoundingClientRect();
|
|
47
|
+
element.style.transformOrigin = `${e.center.x - innerRect.left}px ${e.center.y - innerRect.top}px`;
|
|
48
|
+
if ((_a = e.srcEvent) == null ? void 0 : _a.cancelable) {
|
|
49
|
+
e.srcEvent.preventDefault();
|
|
50
|
+
e.srcEvent.stopPropagation();
|
|
51
|
+
}
|
|
52
|
+
};
|
|
53
|
+
const pinchMove = (e) => {
|
|
54
|
+
var _a;
|
|
55
|
+
updateTransform(e.scale);
|
|
56
|
+
if ((_a = e.srcEvent) == null ? void 0 : _a.cancelable) {
|
|
57
|
+
e.srcEvent.preventDefault();
|
|
58
|
+
e.srcEvent.stopPropagation();
|
|
59
|
+
}
|
|
60
|
+
};
|
|
61
|
+
const pinchEnd = (e) => {
|
|
62
|
+
const delta = (e.scale - 1) * initialZoom;
|
|
63
|
+
zoomProvides.requestZoomBy(delta, { vx: lastCenter.x, vy: lastCenter.y });
|
|
64
|
+
resetTransform();
|
|
65
|
+
initialZoom = 0;
|
|
66
|
+
};
|
|
67
|
+
const setupHammer = async () => {
|
|
68
|
+
try {
|
|
69
|
+
const Hammer = (await import("../hammer-e1aXHboh.js").then((n) => n.h)).default;
|
|
70
|
+
const inputClass = (() => {
|
|
71
|
+
const MOBILE_REGEX = /mobile|tablet|ip(ad|hone|od)|android/i;
|
|
72
|
+
const SUPPORT_TOUCH = "ontouchstart" in window || navigator.maxTouchPoints > 0;
|
|
73
|
+
const SUPPORT_ONLY_TOUCH = SUPPORT_TOUCH && MOBILE_REGEX.test(navigator.userAgent);
|
|
74
|
+
if (SUPPORT_ONLY_TOUCH) return Hammer.TouchInput;
|
|
75
|
+
if (!SUPPORT_TOUCH) return Hammer.MouseInput;
|
|
76
|
+
return Hammer.TouchMouseInput;
|
|
77
|
+
})();
|
|
78
|
+
hammer = new Hammer(element, {
|
|
79
|
+
touchAction: "pan-x pan-y",
|
|
80
|
+
// allow scroll in every direction
|
|
81
|
+
inputClass
|
|
82
|
+
});
|
|
83
|
+
hammer.get("pinch").set({ enable: true, pointers: 2, threshold: 0.1 });
|
|
84
|
+
hammer.on("pinchstart", pinchStart);
|
|
85
|
+
hammer.on("pinchmove", pinchMove);
|
|
86
|
+
hammer.on("pinchend", pinchEnd);
|
|
87
|
+
} catch (error) {
|
|
88
|
+
console.warn("Failed to load HammerJS:", error);
|
|
89
|
+
}
|
|
90
|
+
};
|
|
91
|
+
setupHammer();
|
|
92
|
+
return () => {
|
|
93
|
+
hammer == null ? void 0 : hammer.destroy();
|
|
94
|
+
resetTransform();
|
|
95
|
+
};
|
|
96
|
+
}
|
|
21
97
|
function usePinch() {
|
|
22
98
|
const { provides: viewportProvides } = useCapability("viewport");
|
|
23
99
|
const { provides: zoomProvides } = useZoomCapability();
|
|
@@ -27,78 +103,7 @@ function usePinch() {
|
|
|
27
103
|
if (!element || !viewportProvides || !zoomProvides) {
|
|
28
104
|
return;
|
|
29
105
|
}
|
|
30
|
-
|
|
31
|
-
return;
|
|
32
|
-
}
|
|
33
|
-
let hammer;
|
|
34
|
-
let initialZoom = 0;
|
|
35
|
-
let lastCenter = { x: 0, y: 0 };
|
|
36
|
-
const getState = () => zoomProvides.getState();
|
|
37
|
-
const updateTransform = (scale) => {
|
|
38
|
-
element.style.transform = `scale(${scale})`;
|
|
39
|
-
};
|
|
40
|
-
const resetTransform = () => {
|
|
41
|
-
element.style.transform = "none";
|
|
42
|
-
element.style.transformOrigin = "0 0";
|
|
43
|
-
};
|
|
44
|
-
const pinchStart = (e) => {
|
|
45
|
-
var _a;
|
|
46
|
-
initialZoom = getState().currentZoomLevel;
|
|
47
|
-
const contRect = viewportProvides.getBoundingRect();
|
|
48
|
-
lastCenter = {
|
|
49
|
-
x: e.center.x - contRect.origin.x,
|
|
50
|
-
y: e.center.y - contRect.origin.y
|
|
51
|
-
};
|
|
52
|
-
const innerRect = element.getBoundingClientRect();
|
|
53
|
-
element.style.transformOrigin = `${e.center.x - innerRect.left}px ${e.center.y - innerRect.top}px`;
|
|
54
|
-
if ((_a = e.srcEvent) == null ? void 0 : _a.cancelable) {
|
|
55
|
-
e.srcEvent.preventDefault();
|
|
56
|
-
e.srcEvent.stopPropagation();
|
|
57
|
-
}
|
|
58
|
-
};
|
|
59
|
-
const pinchMove = (e) => {
|
|
60
|
-
var _a;
|
|
61
|
-
updateTransform(e.scale);
|
|
62
|
-
if ((_a = e.srcEvent) == null ? void 0 : _a.cancelable) {
|
|
63
|
-
e.srcEvent.preventDefault();
|
|
64
|
-
e.srcEvent.stopPropagation();
|
|
65
|
-
}
|
|
66
|
-
};
|
|
67
|
-
const pinchEnd = (e) => {
|
|
68
|
-
const delta = (e.scale - 1) * initialZoom;
|
|
69
|
-
zoomProvides.requestZoomBy(delta, { vx: lastCenter.x, vy: lastCenter.y });
|
|
70
|
-
resetTransform();
|
|
71
|
-
initialZoom = 0;
|
|
72
|
-
};
|
|
73
|
-
const setupHammer = async () => {
|
|
74
|
-
try {
|
|
75
|
-
const Hammer = (await import("../hammer-e1aXHboh.js").then((n) => n.h)).default;
|
|
76
|
-
const inputClass = (() => {
|
|
77
|
-
const MOBILE_REGEX = /mobile|tablet|ip(ad|hone|od)|android/i;
|
|
78
|
-
const SUPPORT_TOUCH = "ontouchstart" in window || navigator.maxTouchPoints > 0;
|
|
79
|
-
const SUPPORT_ONLY_TOUCH = SUPPORT_TOUCH && MOBILE_REGEX.test(navigator.userAgent);
|
|
80
|
-
if (SUPPORT_ONLY_TOUCH) return Hammer.TouchInput;
|
|
81
|
-
if (!SUPPORT_TOUCH) return Hammer.MouseInput;
|
|
82
|
-
return Hammer.TouchMouseInput;
|
|
83
|
-
})();
|
|
84
|
-
hammer = new Hammer(element, {
|
|
85
|
-
touchAction: "pan-x pan-y",
|
|
86
|
-
// allow scroll in every direction
|
|
87
|
-
inputClass
|
|
88
|
-
});
|
|
89
|
-
hammer.get("pinch").set({ enable: true, pointers: 2, threshold: 0.1 });
|
|
90
|
-
hammer.on("pinchstart", pinchStart);
|
|
91
|
-
hammer.on("pinchmove", pinchMove);
|
|
92
|
-
hammer.on("pinchend", pinchEnd);
|
|
93
|
-
} catch (error) {
|
|
94
|
-
console.warn("Failed to load HammerJS:", error);
|
|
95
|
-
}
|
|
96
|
-
};
|
|
97
|
-
setupHammer();
|
|
98
|
-
return () => {
|
|
99
|
-
hammer == null ? void 0 : hammer.destroy();
|
|
100
|
-
resetTransform();
|
|
101
|
-
};
|
|
106
|
+
return setupPinchZoom({ element, viewportProvides, zoomProvides });
|
|
102
107
|
}, [viewportProvides, zoomProvides]);
|
|
103
108
|
return { elementRef };
|
|
104
109
|
}
|
package/dist/preact/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sources":["../../src/shared/hooks/use-zoom.ts","../../src/shared/hooks/use-pinch-zoom.ts","../../src/shared/components/pinch-wrapper.tsx","../../src/shared/components/marquee-zoom.tsx"],"sourcesContent":["import { useCapability, usePlugin } from '@embedpdf/core/@framework';\nimport { initialState, ZoomPlugin, ZoomState } from '@embedpdf/plugin-zoom';\nimport { useEffect, useState } from '@framework';\n\nexport const useZoomCapability = () => useCapability<ZoomPlugin>(ZoomPlugin.id);\nexport const useZoomPlugin = () => usePlugin<ZoomPlugin>(ZoomPlugin.id);\n\nexport const useZoom = () => {\n const { provides } = useZoomCapability();\n const [state, setState] = useState<ZoomState>(initialState);\n\n useEffect(() => {\n return provides?.onStateChange((action) => {\n setState(action);\n });\n }, [provides]);\n\n return {\n state,\n provides,\n };\n};\n","import { useEffect, useRef } from '@framework';\nimport { useCapability } from '@embedpdf/core/@framework';\nimport { ViewportPlugin } from '@embedpdf/plugin-viewport';\nimport { ZoomState } from '@embedpdf/plugin-zoom';\n\nimport { useZoomCapability } from './use-zoom';\n\nexport function usePinch() {\n const { provides: viewportProvides } = useCapability<ViewportPlugin>('viewport');\n const { provides: zoomProvides } = useZoomCapability();\n const elementRef = useRef<HTMLDivElement>(null);\n\n useEffect(() => {\n const element = elementRef.current;\n if (!element || !viewportProvides || !zoomProvides) {\n return;\n }\n\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 // Dynamically import and setup Hammer\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();\n\n return () => {\n hammer?.destroy();\n resetTransform();\n };\n }, [viewportProvides, zoomProvides]);\n\n return { elementRef };\n}\n","import { ReactNode, HTMLAttributes, CSSProperties } from '@framework';\n\nimport { usePinch } from '../hooks';\n\ntype PinchWrapperProps = Omit<HTMLAttributes<HTMLDivElement>, 'style'> & {\n children: ReactNode;\n style?: CSSProperties;\n};\n\nexport function PinchWrapper({ children, style, ...props }: PinchWrapperProps) {\n const { elementRef } = usePinch();\n\n return (\n <div\n ref={elementRef}\n {...props}\n style={{\n ...style,\n display: 'block',\n width: 'fit-content',\n overflow: 'visible',\n boxSizing: 'border-box',\n margin: '0px auto',\n }}\n >\n {children}\n </div>\n );\n}\n","import { useEffect, useState } from '@framework';\nimport { Rect } from '@embedpdf/models';\n\nimport { useZoomCapability } from '../hooks/use-zoom';\n\ninterface 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 className?: string;\n /** Stroke / fill colours (defaults below) */\n stroke?: string;\n fill?: string;\n}\n\nexport const MarqueeZoom = ({\n pageIndex,\n scale,\n className,\n stroke = 'rgba(33,150,243,0.8)',\n fill = 'rgba(33,150,243,0.15)',\n}: MarqueeZoomProps) => {\n const { provides: zoomPlugin } = useZoomCapability();\n const [rect, setRect] = useState<Rect | null>(null);\n\n useEffect(() => {\n if (!zoomPlugin) return;\n return zoomPlugin.registerMarqueeOnPage({\n pageIndex,\n scale,\n callback: {\n onPreview: setRect,\n },\n });\n }, [zoomPlugin, pageIndex, scale]);\n\n if (!rect) return null;\n\n return (\n <div\n style={{\n position: 'absolute',\n pointerEvents: 'none',\n left: rect.origin.x * scale,\n top: rect.origin.y * scale,\n width: rect.size.width * scale,\n height: rect.size.height * scale,\n border: `1px solid ${stroke}`,\n background: fill,\n boxSizing: 'border-box',\n }}\n className={className}\n />\n );\n};\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","sources":["../../src/shared/hooks/use-zoom.ts","../../src/shared/utils/pinch-zoom-logic.ts","../../src/shared/hooks/use-pinch-zoom.ts","../../src/shared/components/pinch-wrapper.tsx","../../src/shared/components/marquee-zoom.tsx"],"sourcesContent":["import { useCapability, usePlugin } from '@embedpdf/core/@framework';\nimport { initialState, ZoomPlugin, ZoomState } from '@embedpdf/plugin-zoom';\nimport { useEffect, useState } from '@framework';\n\nexport const useZoomCapability = () => useCapability<ZoomPlugin>(ZoomPlugin.id);\nexport const useZoomPlugin = () => usePlugin<ZoomPlugin>(ZoomPlugin.id);\n\nexport const useZoom = () => {\n const { provides } = useZoomCapability();\n const [state, setState] = useState<ZoomState>(initialState);\n\n useEffect(() => {\n return provides?.onStateChange((action) => {\n setState(action);\n });\n }, [provides]);\n\n return {\n state,\n provides,\n };\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 { useEffect, useRef } from '@framework';\nimport { useCapability } from '@embedpdf/core/@framework';\nimport { ViewportPlugin } from '@embedpdf/plugin-viewport';\n\nimport { setupPinchZoom } from '../utils/pinch-zoom-logic';\nimport { useZoomCapability } from './use-zoom';\n\nexport function usePinch() {\n const { provides: viewportProvides } = useCapability<ViewportPlugin>('viewport');\n const { provides: zoomProvides } = useZoomCapability();\n const elementRef = useRef<HTMLDivElement>(null);\n\n useEffect(() => {\n const element = elementRef.current;\n if (!element || !viewportProvides || !zoomProvides) {\n return;\n }\n\n return setupPinchZoom({ element, viewportProvides, zoomProvides });\n }, [viewportProvides, zoomProvides]);\n\n return { elementRef };\n}\n","import { ReactNode, HTMLAttributes, CSSProperties } from '@framework';\n\nimport { usePinch } from '../hooks';\n\ntype PinchWrapperProps = Omit<HTMLAttributes<HTMLDivElement>, 'style'> & {\n children: ReactNode;\n style?: CSSProperties;\n};\n\nexport function PinchWrapper({ children, style, ...props }: PinchWrapperProps) {\n const { elementRef } = usePinch();\n\n return (\n <div\n ref={elementRef}\n {...props}\n style={{\n ...style,\n display: 'block',\n width: 'fit-content',\n overflow: 'visible',\n boxSizing: 'border-box',\n margin: '0px auto',\n }}\n >\n {children}\n </div>\n );\n}\n","import { useEffect, useState } from '@framework';\nimport { Rect } from '@embedpdf/models';\n\nimport { useZoomCapability } from '../hooks/use-zoom';\n\ninterface 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 className?: string;\n /** Stroke / fill colours (defaults below) */\n stroke?: string;\n fill?: string;\n}\n\nexport const MarqueeZoom = ({\n pageIndex,\n scale,\n className,\n stroke = 'rgba(33,150,243,0.8)',\n fill = 'rgba(33,150,243,0.15)',\n}: MarqueeZoomProps) => {\n const { provides: zoomPlugin } = useZoomCapability();\n const [rect, setRect] = useState<Rect | null>(null);\n\n useEffect(() => {\n if (!zoomPlugin) return;\n return zoomPlugin.registerMarqueeOnPage({\n pageIndex,\n scale,\n callback: {\n onPreview: setRect,\n },\n });\n }, [zoomPlugin, pageIndex, scale]);\n\n if (!rect) return null;\n\n return (\n <div\n style={{\n position: 'absolute',\n pointerEvents: 'none',\n left: rect.origin.x * scale,\n top: rect.origin.y * scale,\n width: rect.size.width * scale,\n height: rect.size.height * scale,\n border: `1px solid ${stroke}`,\n background: fill,\n boxSizing: 'border-box',\n }}\n className={className}\n />\n );\n};\n"],"names":[],"mappings":"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"}
|
package/dist/react/index.cjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("@embedpdf/core/react"),t=require("@embedpdf/plugin-zoom"),
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("@embedpdf/core/react"),t=require("@embedpdf/plugin-zoom"),o=require("react"),n=require("react/jsx-runtime"),r=()=>e.useCapability(t.ZoomPlugin.id);function i({element:e,viewportProvides:t,zoomProvides:o}){if("undefined"==typeof window)return()=>{};let n,r=0,i={x:0,y:0};const s=()=>{e.style.transform="none",e.style.transformOrigin="0 0"},a=n=>{var s;r=o.getState().currentZoomLevel;const a=t.getBoundingRect();i={x:n.center.x-a.origin.x,y:n.center.y-a.origin.y};const l=e.getBoundingClientRect();e.style.transformOrigin=`${n.center.x-l.left}px ${n.center.y-l.top}px`,(null==(s=n.srcEvent)?void 0:s.cancelable)&&(n.srcEvent.preventDefault(),n.srcEvent.stopPropagation())},l=t=>{var o,n;n=t.scale,e.style.transform=`scale(${n})`,(null==(o=t.srcEvent)?void 0:o.cancelable)&&(t.srcEvent.preventDefault(),t.srcEvent.stopPropagation())},c=e=>{const t=(e.scale-1)*r;o.requestZoomBy(t,{vx:i.x,vy:i.y}),s(),r=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})();n=new t(e,{touchAction:"pan-x pan-y",inputClass:o}),n.get("pinch").set({enable:!0,pointers:2,threshold:.1}),n.on("pinchstart",a),n.on("pinchmove",l),n.on("pinchend",c)}catch(t){console.warn("Failed to load HammerJS:",t)}})(),()=>{null==n||n.destroy(),s()}}function s(){const{provides:t}=e.useCapability("viewport"),{provides:n}=r(),s=o.useRef(null);return o.useEffect((()=>{const e=s.current;if(e&&t&&n)return i({element:e,viewportProvides:t,zoomProvides:n})}),[t,n]),{elementRef:s}}exports.MarqueeZoom=({pageIndex:e,scale:t,className:i,stroke:s="rgba(33,150,243,0.8)",fill:a="rgba(33,150,243,0.15)"})=>{const{provides:l}=r(),[c,u]=o.useState(null);return o.useEffect((()=>{if(l)return l.registerMarqueeOnPage({pageIndex:e,scale:t,callback:{onPreview:u}})}),[l,e,t]),c?n.jsx("div",{style:{position:"absolute",pointerEvents:"none",left:c.origin.x*t,top:c.origin.y*t,width:c.size.width*t,height:c.size.height*t,border:`1px solid ${s}`,background:a,boxSizing:"border-box"},className:i}):null},exports.PinchWrapper=function({children:e,style:t,...o}){const{elementRef:r}=s();return n.jsx("div",{ref:r,...o,style:{...t,display:"block",width:"fit-content",overflow:"visible",boxSizing:"border-box",margin:"0px auto"},children:e})},exports.usePinch=s,exports.useZoom=()=>{const{provides:e}=r(),[n,i]=o.useState(t.initialState);return o.useEffect((()=>null==e?void 0:e.onStateChange((e=>{i(e)}))),[e]),{state:n,provides:e}},exports.useZoomCapability=r,exports.useZoomPlugin=()=>e.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
|
package/dist/react/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.cjs","sources":["../../src/shared/hooks/use-zoom.ts","../../src/shared/hooks/use-pinch-zoom.ts","../../src/shared/components/marquee-zoom.tsx","../../src/shared/components/pinch-wrapper.tsx"],"sourcesContent":["import { useCapability, usePlugin } from '@embedpdf/core/@framework';\nimport { initialState, ZoomPlugin, ZoomState } from '@embedpdf/plugin-zoom';\nimport { useEffect, useState } from '@framework';\n\nexport const useZoomCapability = () => useCapability<ZoomPlugin>(ZoomPlugin.id);\nexport const useZoomPlugin = () => usePlugin<ZoomPlugin>(ZoomPlugin.id);\n\nexport const useZoom = () => {\n const { provides } = useZoomCapability();\n const [state, setState] = useState<ZoomState>(initialState);\n\n useEffect(() => {\n return provides?.onStateChange((action) => {\n setState(action);\n });\n }, [provides]);\n\n return {\n state,\n provides,\n };\n};\n","import { useEffect, useRef } from '@framework';\nimport { useCapability } from '@embedpdf/core/@framework';\nimport { ViewportPlugin } from '@embedpdf/plugin-viewport';\nimport { ZoomState } from '@embedpdf/plugin-zoom';\n\nimport { useZoomCapability } from './use-zoom';\n\nexport function usePinch() {\n const { provides: viewportProvides } = useCapability<ViewportPlugin>('viewport');\n const { provides: zoomProvides } = useZoomCapability();\n const elementRef = useRef<HTMLDivElement>(null);\n\n useEffect(() => {\n const element = elementRef.current;\n if (!element || !viewportProvides || !zoomProvides) {\n return;\n }\n\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 // Dynamically import and setup Hammer\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();\n\n return () => {\n hammer?.destroy();\n resetTransform();\n };\n }, [viewportProvides, zoomProvides]);\n\n return { elementRef };\n}\n","import { useEffect, useState } from '@framework';\nimport { Rect } from '@embedpdf/models';\n\nimport { useZoomCapability } from '../hooks/use-zoom';\n\ninterface 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 className?: string;\n /** Stroke / fill colours (defaults below) */\n stroke?: string;\n fill?: string;\n}\n\nexport const MarqueeZoom = ({\n pageIndex,\n scale,\n className,\n stroke = 'rgba(33,150,243,0.8)',\n fill = 'rgba(33,150,243,0.15)',\n}: MarqueeZoomProps) => {\n const { provides: zoomPlugin } = useZoomCapability();\n const [rect, setRect] = useState<Rect | null>(null);\n\n useEffect(() => {\n if (!zoomPlugin) return;\n return zoomPlugin.registerMarqueeOnPage({\n pageIndex,\n scale,\n callback: {\n onPreview: setRect,\n },\n });\n }, [zoomPlugin, pageIndex, scale]);\n\n if (!rect) return null;\n\n return (\n <div\n style={{\n position: 'absolute',\n pointerEvents: 'none',\n left: rect.origin.x * scale,\n top: rect.origin.y * scale,\n width: rect.size.width * scale,\n height: rect.size.height * scale,\n border: `1px solid ${stroke}`,\n background: fill,\n boxSizing: 'border-box',\n }}\n className={className}\n />\n );\n};\n","import { ReactNode, HTMLAttributes, CSSProperties } from '@framework';\n\nimport { usePinch } from '../hooks';\n\ntype PinchWrapperProps = Omit<HTMLAttributes<HTMLDivElement>, 'style'> & {\n children: ReactNode;\n style?: CSSProperties;\n};\n\nexport function PinchWrapper({ children, style, ...props }: PinchWrapperProps) {\n const { elementRef } = usePinch();\n\n return (\n <div\n ref={elementRef}\n {...props}\n style={{\n ...style,\n display: 'block',\n width: 'fit-content',\n overflow: 'visible',\n boxSizing: 'border-box',\n margin: '0px auto',\n }}\n >\n {children}\n </div>\n );\n}\n"],"names":["useZoomCapability","useCapability","ZoomPlugin","id","usePinch","provides","viewportProvides","zoomProvides","elementRef","useRef","useEffect","element","current","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","pageIndex","className","stroke","fill","zoomPlugin","rect","setRect","useState","registerMarqueeOnPage","callback","onPreview","jsxRuntime","jsx","position","pointerEvents","width","size","height","border","background","boxSizing","children","props","ref","display","overflow","margin","state","setState","initialState","onStateChange","action","usePlugin"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.cjs","sources":["../../src/shared/hooks/use-zoom.ts","../../src/shared/utils/pinch-zoom-logic.ts","../../src/shared/hooks/use-pinch-zoom.ts","../../src/shared/components/marquee-zoom.tsx","../../src/shared/components/pinch-wrapper.tsx"],"sourcesContent":["import { useCapability, usePlugin } from '@embedpdf/core/@framework';\nimport { initialState, ZoomPlugin, ZoomState } from '@embedpdf/plugin-zoom';\nimport { useEffect, useState } from '@framework';\n\nexport const useZoomCapability = () => useCapability<ZoomPlugin>(ZoomPlugin.id);\nexport const useZoomPlugin = () => usePlugin<ZoomPlugin>(ZoomPlugin.id);\n\nexport const useZoom = () => {\n const { provides } = useZoomCapability();\n const [state, setState] = useState<ZoomState>(initialState);\n\n useEffect(() => {\n return provides?.onStateChange((action) => {\n setState(action);\n });\n }, [provides]);\n\n return {\n state,\n provides,\n };\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 { useEffect, useRef } from '@framework';\nimport { useCapability } from '@embedpdf/core/@framework';\nimport { ViewportPlugin } from '@embedpdf/plugin-viewport';\n\nimport { setupPinchZoom } from '../utils/pinch-zoom-logic';\nimport { useZoomCapability } from './use-zoom';\n\nexport function usePinch() {\n const { provides: viewportProvides } = useCapability<ViewportPlugin>('viewport');\n const { provides: zoomProvides } = useZoomCapability();\n const elementRef = useRef<HTMLDivElement>(null);\n\n useEffect(() => {\n const element = elementRef.current;\n if (!element || !viewportProvides || !zoomProvides) {\n return;\n }\n\n return setupPinchZoom({ element, viewportProvides, zoomProvides });\n }, [viewportProvides, zoomProvides]);\n\n return { elementRef };\n}\n","import { useEffect, useState } from '@framework';\nimport { Rect } from '@embedpdf/models';\n\nimport { useZoomCapability } from '../hooks/use-zoom';\n\ninterface 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 className?: string;\n /** Stroke / fill colours (defaults below) */\n stroke?: string;\n fill?: string;\n}\n\nexport const MarqueeZoom = ({\n pageIndex,\n scale,\n className,\n stroke = 'rgba(33,150,243,0.8)',\n fill = 'rgba(33,150,243,0.15)',\n}: MarqueeZoomProps) => {\n const { provides: zoomPlugin } = useZoomCapability();\n const [rect, setRect] = useState<Rect | null>(null);\n\n useEffect(() => {\n if (!zoomPlugin) return;\n return zoomPlugin.registerMarqueeOnPage({\n pageIndex,\n scale,\n callback: {\n onPreview: setRect,\n },\n });\n }, [zoomPlugin, pageIndex, scale]);\n\n if (!rect) return null;\n\n return (\n <div\n style={{\n position: 'absolute',\n pointerEvents: 'none',\n left: rect.origin.x * scale,\n top: rect.origin.y * scale,\n width: rect.size.width * scale,\n height: rect.size.height * scale,\n border: `1px solid ${stroke}`,\n background: fill,\n boxSizing: 'border-box',\n }}\n className={className}\n />\n );\n};\n","import { ReactNode, HTMLAttributes, CSSProperties } from '@framework';\n\nimport { usePinch } from '../hooks';\n\ntype PinchWrapperProps = Omit<HTMLAttributes<HTMLDivElement>, 'style'> & {\n children: ReactNode;\n style?: CSSProperties;\n};\n\nexport function PinchWrapper({ children, style, ...props }: PinchWrapperProps) {\n const { elementRef } = usePinch();\n\n return (\n <div\n ref={elementRef}\n {...props}\n style={{\n ...style,\n display: 'block',\n width: 'fit-content',\n overflow: 'visible',\n boxSizing: 'border-box',\n margin: '0px auto',\n }}\n >\n {children}\n </div>\n );\n}\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","provides","elementRef","useRef","useEffect","current","pageIndex","className","stroke","fill","zoomPlugin","rect","setRect","useState","registerMarqueeOnPage","callback","onPreview","jsxRuntime","jsx","position","pointerEvents","width","size","height","border","background","boxSizing","children","props","ref","display","overflow","margin","state","setState","initialState","onStateChange","action","usePlugin"],"mappings":"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"}
|
package/dist/react/index.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { useCapability, usePlugin } from "@embedpdf/core/react";
|
|
2
2
|
import { ZoomPlugin, initialState } from "@embedpdf/plugin-zoom";
|
|
3
|
+
export * from "@embedpdf/plugin-zoom";
|
|
3
4
|
import { useState, useEffect, useRef } from "react";
|
|
4
5
|
import { jsx } from "react/jsx-runtime";
|
|
5
6
|
const useZoomCapability = () => useCapability(ZoomPlugin.id);
|
|
@@ -17,6 +18,81 @@ const useZoom = () => {
|
|
|
17
18
|
provides
|
|
18
19
|
};
|
|
19
20
|
};
|
|
21
|
+
function setupPinchZoom({ element, viewportProvides, zoomProvides }) {
|
|
22
|
+
if (typeof window === "undefined") {
|
|
23
|
+
return () => {
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
let hammer;
|
|
27
|
+
let initialZoom = 0;
|
|
28
|
+
let lastCenter = { x: 0, y: 0 };
|
|
29
|
+
const getState = () => zoomProvides.getState();
|
|
30
|
+
const updateTransform = (scale) => {
|
|
31
|
+
element.style.transform = `scale(${scale})`;
|
|
32
|
+
};
|
|
33
|
+
const resetTransform = () => {
|
|
34
|
+
element.style.transform = "none";
|
|
35
|
+
element.style.transformOrigin = "0 0";
|
|
36
|
+
};
|
|
37
|
+
const pinchStart = (e) => {
|
|
38
|
+
var _a;
|
|
39
|
+
initialZoom = getState().currentZoomLevel;
|
|
40
|
+
const contRect = viewportProvides.getBoundingRect();
|
|
41
|
+
lastCenter = {
|
|
42
|
+
x: e.center.x - contRect.origin.x,
|
|
43
|
+
y: e.center.y - contRect.origin.y
|
|
44
|
+
};
|
|
45
|
+
const innerRect = element.getBoundingClientRect();
|
|
46
|
+
element.style.transformOrigin = `${e.center.x - innerRect.left}px ${e.center.y - innerRect.top}px`;
|
|
47
|
+
if ((_a = e.srcEvent) == null ? void 0 : _a.cancelable) {
|
|
48
|
+
e.srcEvent.preventDefault();
|
|
49
|
+
e.srcEvent.stopPropagation();
|
|
50
|
+
}
|
|
51
|
+
};
|
|
52
|
+
const pinchMove = (e) => {
|
|
53
|
+
var _a;
|
|
54
|
+
updateTransform(e.scale);
|
|
55
|
+
if ((_a = e.srcEvent) == null ? void 0 : _a.cancelable) {
|
|
56
|
+
e.srcEvent.preventDefault();
|
|
57
|
+
e.srcEvent.stopPropagation();
|
|
58
|
+
}
|
|
59
|
+
};
|
|
60
|
+
const pinchEnd = (e) => {
|
|
61
|
+
const delta = (e.scale - 1) * initialZoom;
|
|
62
|
+
zoomProvides.requestZoomBy(delta, { vx: lastCenter.x, vy: lastCenter.y });
|
|
63
|
+
resetTransform();
|
|
64
|
+
initialZoom = 0;
|
|
65
|
+
};
|
|
66
|
+
const setupHammer = async () => {
|
|
67
|
+
try {
|
|
68
|
+
const Hammer = (await import("../hammer-e1aXHboh.js").then((n) => n.h)).default;
|
|
69
|
+
const inputClass = (() => {
|
|
70
|
+
const MOBILE_REGEX = /mobile|tablet|ip(ad|hone|od)|android/i;
|
|
71
|
+
const SUPPORT_TOUCH = "ontouchstart" in window || navigator.maxTouchPoints > 0;
|
|
72
|
+
const SUPPORT_ONLY_TOUCH = SUPPORT_TOUCH && MOBILE_REGEX.test(navigator.userAgent);
|
|
73
|
+
if (SUPPORT_ONLY_TOUCH) return Hammer.TouchInput;
|
|
74
|
+
if (!SUPPORT_TOUCH) return Hammer.MouseInput;
|
|
75
|
+
return Hammer.TouchMouseInput;
|
|
76
|
+
})();
|
|
77
|
+
hammer = new Hammer(element, {
|
|
78
|
+
touchAction: "pan-x pan-y",
|
|
79
|
+
// allow scroll in every direction
|
|
80
|
+
inputClass
|
|
81
|
+
});
|
|
82
|
+
hammer.get("pinch").set({ enable: true, pointers: 2, threshold: 0.1 });
|
|
83
|
+
hammer.on("pinchstart", pinchStart);
|
|
84
|
+
hammer.on("pinchmove", pinchMove);
|
|
85
|
+
hammer.on("pinchend", pinchEnd);
|
|
86
|
+
} catch (error) {
|
|
87
|
+
console.warn("Failed to load HammerJS:", error);
|
|
88
|
+
}
|
|
89
|
+
};
|
|
90
|
+
setupHammer();
|
|
91
|
+
return () => {
|
|
92
|
+
hammer == null ? void 0 : hammer.destroy();
|
|
93
|
+
resetTransform();
|
|
94
|
+
};
|
|
95
|
+
}
|
|
20
96
|
function usePinch() {
|
|
21
97
|
const { provides: viewportProvides } = useCapability("viewport");
|
|
22
98
|
const { provides: zoomProvides } = useZoomCapability();
|
|
@@ -26,78 +102,7 @@ function usePinch() {
|
|
|
26
102
|
if (!element || !viewportProvides || !zoomProvides) {
|
|
27
103
|
return;
|
|
28
104
|
}
|
|
29
|
-
|
|
30
|
-
return;
|
|
31
|
-
}
|
|
32
|
-
let hammer;
|
|
33
|
-
let initialZoom = 0;
|
|
34
|
-
let lastCenter = { x: 0, y: 0 };
|
|
35
|
-
const getState = () => zoomProvides.getState();
|
|
36
|
-
const updateTransform = (scale) => {
|
|
37
|
-
element.style.transform = `scale(${scale})`;
|
|
38
|
-
};
|
|
39
|
-
const resetTransform = () => {
|
|
40
|
-
element.style.transform = "none";
|
|
41
|
-
element.style.transformOrigin = "0 0";
|
|
42
|
-
};
|
|
43
|
-
const pinchStart = (e) => {
|
|
44
|
-
var _a;
|
|
45
|
-
initialZoom = getState().currentZoomLevel;
|
|
46
|
-
const contRect = viewportProvides.getBoundingRect();
|
|
47
|
-
lastCenter = {
|
|
48
|
-
x: e.center.x - contRect.origin.x,
|
|
49
|
-
y: e.center.y - contRect.origin.y
|
|
50
|
-
};
|
|
51
|
-
const innerRect = element.getBoundingClientRect();
|
|
52
|
-
element.style.transformOrigin = `${e.center.x - innerRect.left}px ${e.center.y - innerRect.top}px`;
|
|
53
|
-
if ((_a = e.srcEvent) == null ? void 0 : _a.cancelable) {
|
|
54
|
-
e.srcEvent.preventDefault();
|
|
55
|
-
e.srcEvent.stopPropagation();
|
|
56
|
-
}
|
|
57
|
-
};
|
|
58
|
-
const pinchMove = (e) => {
|
|
59
|
-
var _a;
|
|
60
|
-
updateTransform(e.scale);
|
|
61
|
-
if ((_a = e.srcEvent) == null ? void 0 : _a.cancelable) {
|
|
62
|
-
e.srcEvent.preventDefault();
|
|
63
|
-
e.srcEvent.stopPropagation();
|
|
64
|
-
}
|
|
65
|
-
};
|
|
66
|
-
const pinchEnd = (e) => {
|
|
67
|
-
const delta = (e.scale - 1) * initialZoom;
|
|
68
|
-
zoomProvides.requestZoomBy(delta, { vx: lastCenter.x, vy: lastCenter.y });
|
|
69
|
-
resetTransform();
|
|
70
|
-
initialZoom = 0;
|
|
71
|
-
};
|
|
72
|
-
const setupHammer = async () => {
|
|
73
|
-
try {
|
|
74
|
-
const Hammer = (await import("../hammer-e1aXHboh.js").then((n) => n.h)).default;
|
|
75
|
-
const inputClass = (() => {
|
|
76
|
-
const MOBILE_REGEX = /mobile|tablet|ip(ad|hone|od)|android/i;
|
|
77
|
-
const SUPPORT_TOUCH = "ontouchstart" in window || navigator.maxTouchPoints > 0;
|
|
78
|
-
const SUPPORT_ONLY_TOUCH = SUPPORT_TOUCH && MOBILE_REGEX.test(navigator.userAgent);
|
|
79
|
-
if (SUPPORT_ONLY_TOUCH) return Hammer.TouchInput;
|
|
80
|
-
if (!SUPPORT_TOUCH) return Hammer.MouseInput;
|
|
81
|
-
return Hammer.TouchMouseInput;
|
|
82
|
-
})();
|
|
83
|
-
hammer = new Hammer(element, {
|
|
84
|
-
touchAction: "pan-x pan-y",
|
|
85
|
-
// allow scroll in every direction
|
|
86
|
-
inputClass
|
|
87
|
-
});
|
|
88
|
-
hammer.get("pinch").set({ enable: true, pointers: 2, threshold: 0.1 });
|
|
89
|
-
hammer.on("pinchstart", pinchStart);
|
|
90
|
-
hammer.on("pinchmove", pinchMove);
|
|
91
|
-
hammer.on("pinchend", pinchEnd);
|
|
92
|
-
} catch (error) {
|
|
93
|
-
console.warn("Failed to load HammerJS:", error);
|
|
94
|
-
}
|
|
95
|
-
};
|
|
96
|
-
setupHammer();
|
|
97
|
-
return () => {
|
|
98
|
-
hammer == null ? void 0 : hammer.destroy();
|
|
99
|
-
resetTransform();
|
|
100
|
-
};
|
|
105
|
+
return setupPinchZoom({ element, viewportProvides, zoomProvides });
|
|
101
106
|
}, [viewportProvides, zoomProvides]);
|
|
102
107
|
return { elementRef };
|
|
103
108
|
}
|
package/dist/react/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sources":["../../src/shared/hooks/use-zoom.ts","../../src/shared/hooks/use-pinch-zoom.ts","../../src/shared/components/pinch-wrapper.tsx","../../src/shared/components/marquee-zoom.tsx"],"sourcesContent":["import { useCapability, usePlugin } from '@embedpdf/core/@framework';\nimport { initialState, ZoomPlugin, ZoomState } from '@embedpdf/plugin-zoom';\nimport { useEffect, useState } from '@framework';\n\nexport const useZoomCapability = () => useCapability<ZoomPlugin>(ZoomPlugin.id);\nexport const useZoomPlugin = () => usePlugin<ZoomPlugin>(ZoomPlugin.id);\n\nexport const useZoom = () => {\n const { provides } = useZoomCapability();\n const [state, setState] = useState<ZoomState>(initialState);\n\n useEffect(() => {\n return provides?.onStateChange((action) => {\n setState(action);\n });\n }, [provides]);\n\n return {\n state,\n provides,\n };\n};\n","import { useEffect, useRef } from '@framework';\nimport { useCapability } from '@embedpdf/core/@framework';\nimport { ViewportPlugin } from '@embedpdf/plugin-viewport';\nimport { ZoomState } from '@embedpdf/plugin-zoom';\n\nimport { useZoomCapability } from './use-zoom';\n\nexport function usePinch() {\n const { provides: viewportProvides } = useCapability<ViewportPlugin>('viewport');\n const { provides: zoomProvides } = useZoomCapability();\n const elementRef = useRef<HTMLDivElement>(null);\n\n useEffect(() => {\n const element = elementRef.current;\n if (!element || !viewportProvides || !zoomProvides) {\n return;\n }\n\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 // Dynamically import and setup Hammer\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();\n\n return () => {\n hammer?.destroy();\n resetTransform();\n };\n }, [viewportProvides, zoomProvides]);\n\n return { elementRef };\n}\n","import { ReactNode, HTMLAttributes, CSSProperties } from '@framework';\n\nimport { usePinch } from '../hooks';\n\ntype PinchWrapperProps = Omit<HTMLAttributes<HTMLDivElement>, 'style'> & {\n children: ReactNode;\n style?: CSSProperties;\n};\n\nexport function PinchWrapper({ children, style, ...props }: PinchWrapperProps) {\n const { elementRef } = usePinch();\n\n return (\n <div\n ref={elementRef}\n {...props}\n style={{\n ...style,\n display: 'block',\n width: 'fit-content',\n overflow: 'visible',\n boxSizing: 'border-box',\n margin: '0px auto',\n }}\n >\n {children}\n </div>\n );\n}\n","import { useEffect, useState } from '@framework';\nimport { Rect } from '@embedpdf/models';\n\nimport { useZoomCapability } from '../hooks/use-zoom';\n\ninterface 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 className?: string;\n /** Stroke / fill colours (defaults below) */\n stroke?: string;\n fill?: string;\n}\n\nexport const MarqueeZoom = ({\n pageIndex,\n scale,\n className,\n stroke = 'rgba(33,150,243,0.8)',\n fill = 'rgba(33,150,243,0.15)',\n}: MarqueeZoomProps) => {\n const { provides: zoomPlugin } = useZoomCapability();\n const [rect, setRect] = useState<Rect | null>(null);\n\n useEffect(() => {\n if (!zoomPlugin) return;\n return zoomPlugin.registerMarqueeOnPage({\n pageIndex,\n scale,\n callback: {\n onPreview: setRect,\n },\n });\n }, [zoomPlugin, pageIndex, scale]);\n\n if (!rect) return null;\n\n return (\n <div\n style={{\n position: 'absolute',\n pointerEvents: 'none',\n left: rect.origin.x * scale,\n top: rect.origin.y * scale,\n width: rect.size.width * scale,\n height: rect.size.height * scale,\n border: `1px solid ${stroke}`,\n background: fill,\n boxSizing: 'border-box',\n }}\n className={className}\n />\n );\n};\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","sources":["../../src/shared/hooks/use-zoom.ts","../../src/shared/utils/pinch-zoom-logic.ts","../../src/shared/hooks/use-pinch-zoom.ts","../../src/shared/components/pinch-wrapper.tsx","../../src/shared/components/marquee-zoom.tsx"],"sourcesContent":["import { useCapability, usePlugin } from '@embedpdf/core/@framework';\nimport { initialState, ZoomPlugin, ZoomState } from '@embedpdf/plugin-zoom';\nimport { useEffect, useState } from '@framework';\n\nexport const useZoomCapability = () => useCapability<ZoomPlugin>(ZoomPlugin.id);\nexport const useZoomPlugin = () => usePlugin<ZoomPlugin>(ZoomPlugin.id);\n\nexport const useZoom = () => {\n const { provides } = useZoomCapability();\n const [state, setState] = useState<ZoomState>(initialState);\n\n useEffect(() => {\n return provides?.onStateChange((action) => {\n setState(action);\n });\n }, [provides]);\n\n return {\n state,\n provides,\n };\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 { useEffect, useRef } from '@framework';\nimport { useCapability } from '@embedpdf/core/@framework';\nimport { ViewportPlugin } from '@embedpdf/plugin-viewport';\n\nimport { setupPinchZoom } from '../utils/pinch-zoom-logic';\nimport { useZoomCapability } from './use-zoom';\n\nexport function usePinch() {\n const { provides: viewportProvides } = useCapability<ViewportPlugin>('viewport');\n const { provides: zoomProvides } = useZoomCapability();\n const elementRef = useRef<HTMLDivElement>(null);\n\n useEffect(() => {\n const element = elementRef.current;\n if (!element || !viewportProvides || !zoomProvides) {\n return;\n }\n\n return setupPinchZoom({ element, viewportProvides, zoomProvides });\n }, [viewportProvides, zoomProvides]);\n\n return { elementRef };\n}\n","import { ReactNode, HTMLAttributes, CSSProperties } from '@framework';\n\nimport { usePinch } from '../hooks';\n\ntype PinchWrapperProps = Omit<HTMLAttributes<HTMLDivElement>, 'style'> & {\n children: ReactNode;\n style?: CSSProperties;\n};\n\nexport function PinchWrapper({ children, style, ...props }: PinchWrapperProps) {\n const { elementRef } = usePinch();\n\n return (\n <div\n ref={elementRef}\n {...props}\n style={{\n ...style,\n display: 'block',\n width: 'fit-content',\n overflow: 'visible',\n boxSizing: 'border-box',\n margin: '0px auto',\n }}\n >\n {children}\n </div>\n );\n}\n","import { useEffect, useState } from '@framework';\nimport { Rect } from '@embedpdf/models';\n\nimport { useZoomCapability } from '../hooks/use-zoom';\n\ninterface 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 className?: string;\n /** Stroke / fill colours (defaults below) */\n stroke?: string;\n fill?: string;\n}\n\nexport const MarqueeZoom = ({\n pageIndex,\n scale,\n className,\n stroke = 'rgba(33,150,243,0.8)',\n fill = 'rgba(33,150,243,0.15)',\n}: MarqueeZoomProps) => {\n const { provides: zoomPlugin } = useZoomCapability();\n const [rect, setRect] = useState<Rect | null>(null);\n\n useEffect(() => {\n if (!zoomPlugin) return;\n return zoomPlugin.registerMarqueeOnPage({\n pageIndex,\n scale,\n callback: {\n onPreview: setRect,\n },\n });\n }, [zoomPlugin, pageIndex, scale]);\n\n if (!rect) return null;\n\n return (\n <div\n style={{\n position: 'absolute',\n pointerEvents: 'none',\n left: rect.origin.x * scale,\n top: rect.origin.y * scale,\n width: rect.size.width * scale,\n height: rect.size.height * scale,\n border: `1px solid ${stroke}`,\n background: fill,\n boxSizing: 'border-box',\n }}\n className={className}\n />\n );\n};\n"],"names":[],"mappings":";;;;;AAIO,MAAM,oBAAoB,MAAM,cAA0B,WAAW,EAAE;AACvE,MAAM,gBAAgB,MAAM,UAAsB,WAAW,EAAE;AAE/D,MAAM,UAAU,MAAM;AACrB,QAAA,EAAE,SAAS,IAAI,kBAAkB;AACvC,QAAM,CAAC,OAAO,QAAQ,IAAI,SAAoB,YAAY;AAE1D,YAAU,MAAM;AACP,WAAA,qCAAU,cAAc,CAAC,WAAW;AACzC,eAAS,MAAM;AAAA,IAAA;AAAA,EAChB,GACA,CAAC,QAAQ,CAAC;AAEN,SAAA;AAAA,IACL;AAAA,IACA;AAAA,EACF;AACF;ACZO,SAAS,eAAe,EAAE,SAAS,kBAAkB,gBAA+B;AAErF,MAAA,OAAO,WAAW,aAAa;AACjC,WAAO,MAAM;AAAA,IAAC;AAAA,EAAA;AAGZ,MAAA;AACJ,MAAI,cAAc;AAClB,MAAI,aAAa,EAAE,GAAG,GAAG,GAAG,EAAE;AAExB,QAAA,WAAW,MAAiB,aAAa,SAAS;AAElD,QAAA,kBAAkB,CAAC,UAAkB;AAEjC,YAAA,MAAM,YAAY,SAAS,KAAK;AAAA,EAC1C;AAEA,QAAM,iBAAiB,MAAM;AAC3B,YAAQ,MAAM,YAAY;AAC1B,YAAQ,MAAM,kBAAkB;AAAA,EAClC;AAEM,QAAA,aAAa,CAAC,MAAmB;;AACrC,kBAAc,WAAW;AAEnB,UAAA,WAAW,iBAAiB,gBAAgB;AAErC,iBAAA;AAAA,MACX,GAAG,EAAE,OAAO,IAAI,SAAS,OAAO;AAAA,MAChC,GAAG,EAAE,OAAO,IAAI,SAAS,OAAO;AAAA,IAClC;AAGM,UAAA,YAAY,QAAQ,sBAAsB;AAChD,YAAQ,MAAM,kBAAkB,GAAG,EAAE,OAAO,IAAI,UAAU,IAAI,MAAM,EAAE,OAAO,IAAI,UAAU,GAAG;AAG1F,SAAA,OAAE,aAAF,mBAAY,YAAY;AAC1B,QAAE,SAAS,eAAe;AAC1B,QAAE,SAAS,gBAAgB;AAAA,IAAA;AAAA,EAE/B;AAEM,QAAA,YAAY,CAAC,MAAmB;;AACpC,oBAAgB,EAAE,KAAK;AACnB,SAAA,OAAE,aAAF,mBAAY,YAAY;AAC1B,QAAE,SAAS,eAAe;AAC1B,QAAE,SAAS,gBAAgB;AAAA,IAAA;AAAA,EAE/B;AAEM,QAAA,WAAW,CAAC,MAAmB;AAE7B,UAAA,SAAS,EAAE,QAAQ,KAAK;AACjB,iBAAA,cAAc,OAAO,EAAE,IAAI,WAAW,GAAG,IAAI,WAAW,GAAG;AAEzD,mBAAA;AACD,kBAAA;AAAA,EAChB;AAGA,QAAM,cAAc,YAAY;AAC1B,QAAA;AACF,YAAM,UAAU,MAAM,OAAO,uBAAU,EAAG,KAAA,OAAA,EAAA,CAAA,GAAA;AAK1C,YAAM,cAAc,MAAM;AACxB,cAAM,eAAe;AACrB,cAAM,gBAAgB,kBAAkB,UAAU,UAAU,iBAAiB;AAC7E,cAAM,qBAAqB,iBAAiB,aAAa,KAAK,UAAU,SAAS;AAC7E,YAAA,2BAA2B,OAAO;AAClC,YAAA,CAAC,cAAe,QAAO,OAAO;AAClC,eAAO,OAAO;AAAA,MAAA,GACb;AAEM,eAAA,IAAI,OAAO,SAAS;AAAA,QAC3B,aAAa;AAAA;AAAA,QACb;AAAA,MAAA,CACD;AAEM,aAAA,IAAI,OAAO,EAAE,IAAI,EAAE,QAAQ,MAAM,UAAU,GAAG,WAAW,IAAA,CAAK;AAE9D,aAAA,GAAG,cAAc,UAAU;AAC3B,aAAA,GAAG,aAAa,SAAS;AACzB,aAAA,GAAG,YAAY,QAAQ;AAAA,aACvB,OAAO;AACN,cAAA,KAAK,4BAA4B,KAAK;AAAA,IAAA;AAAA,EAElD;AAEY,cAAA;AAGZ,SAAO,MAAM;AACX,qCAAQ;AACO,mBAAA;AAAA,EACjB;AACF;ACrGO,SAAS,WAAW;AACzB,QAAM,EAAE,UAAU,qBAAqB,cAA8B,UAAU;AAC/E,QAAM,EAAE,UAAU,aAAa,IAAI,kBAAkB;AAC/C,QAAA,aAAa,OAAuB,IAAI;AAE9C,YAAU,MAAM;AACd,UAAM,UAAU,WAAW;AAC3B,QAAI,CAAC,WAAW,CAAC,oBAAoB,CAAC,cAAc;AAClD;AAAA,IAAA;AAGF,WAAO,eAAe,EAAE,SAAS,kBAAkB,cAAc;AAAA,EAAA,GAChE,CAAC,kBAAkB,YAAY,CAAC;AAEnC,SAAO,EAAE,WAAW;AACtB;ACbO,SAAS,aAAa,EAAE,UAAU,OAAO,GAAG,SAA4B;AACvE,QAAA,EAAE,WAAW,IAAI,SAAS;AAG9B,SAAA;AAAA,IAAC;AAAA,IAAA;AAAA,MACC,KAAK;AAAA,MACJ,GAAG;AAAA,MACJ,OAAO;AAAA,QACL,GAAG;AAAA,QACH,SAAS;AAAA,QACT,OAAO;AAAA,QACP,UAAU;AAAA,QACV,WAAW;AAAA,QACX,QAAQ;AAAA,MACV;AAAA,MAEC;AAAA,IAAA;AAAA,EACH;AAEJ;ACXO,MAAM,cAAc,CAAC;AAAA,EAC1B;AAAA,EACA;AAAA,EACA;AAAA,EACA,SAAS;AAAA,EACT,OAAO;AACT,MAAwB;AACtB,QAAM,EAAE,UAAU,WAAW,IAAI,kBAAkB;AACnD,QAAM,CAAC,MAAM,OAAO,IAAI,SAAsB,IAAI;AAElD,YAAU,MAAM;AACd,QAAI,CAAC,WAAY;AACjB,WAAO,WAAW,sBAAsB;AAAA,MACtC;AAAA,MACA;AAAA,MACA,UAAU;AAAA,QACR,WAAW;AAAA,MAAA;AAAA,IACb,CACD;AAAA,EACA,GAAA,CAAC,YAAY,WAAW,KAAK,CAAC;AAE7B,MAAA,CAAC,KAAa,QAAA;AAGhB,SAAA;AAAA,IAAC;AAAA,IAAA;AAAA,MACC,OAAO;AAAA,QACL,UAAU;AAAA,QACV,eAAe;AAAA,QACf,MAAM,KAAK,OAAO,IAAI;AAAA,QACtB,KAAK,KAAK,OAAO,IAAI;AAAA,QACrB,OAAO,KAAK,KAAK,QAAQ;AAAA,QACzB,QAAQ,KAAK,KAAK,SAAS;AAAA,QAC3B,QAAQ,aAAa,MAAM;AAAA,QAC3B,YAAY;AAAA,QACZ,WAAW;AAAA,MACb;AAAA,MACA;AAAA,IAAA;AAAA,EACF;AAEJ;"}
|
|
@@ -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,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,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,16 @@
|
|
|
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
|
+
declare const _default: import('vue').DefineComponent<MarqueeZoomProps, {}, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {}, string, import('vue').PublicProps, Readonly<MarqueeZoomProps> & Readonly<{}>, {
|
|
13
|
+
fill: string;
|
|
14
|
+
stroke: string;
|
|
15
|
+
}, {}, {}, {}, string, import('vue').ComponentProvideOptions, false, {}, any>;
|
|
16
|
+
export default _default;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
declare var __VLS_1: {};
|
|
2
|
+
type __VLS_Slots = {} & {
|
|
3
|
+
default?: (props: typeof __VLS_1) => any;
|
|
4
|
+
};
|
|
5
|
+
declare const __VLS_component: import('vue').DefineComponent<{}, {}, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {}, string, import('vue').PublicProps, Readonly<{}> & Readonly<{}>, {}, {}, {}, {}, string, import('vue').ComponentProvideOptions, true, {}, any>;
|
|
6
|
+
declare const _default: __VLS_WithSlots<typeof __VLS_component, __VLS_Slots>;
|
|
7
|
+
export default _default;
|
|
8
|
+
type __VLS_WithSlots<T, S> = T & {
|
|
9
|
+
new (): {
|
|
10
|
+
$slots: S;
|
|
11
|
+
};
|
|
12
|
+
};
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { ZoomPlugin, ZoomState } from '../../lib/index.ts';
|
|
2
|
+
export declare const useZoomCapability: () => import('@embedpdf/core/vue').CapabilityState<Readonly<import('../../lib/index.ts').ZoomCapability>>;
|
|
3
|
+
export declare const useZoomPlugin: () => import('@embedpdf/core/vue').PluginState<ZoomPlugin>;
|
|
4
|
+
export declare const useZoom: () => {
|
|
5
|
+
state: import('vue').Ref<{
|
|
6
|
+
zoomLevel: import('../../lib/index.ts').ZoomLevel;
|
|
7
|
+
currentZoomLevel: number;
|
|
8
|
+
}, ZoomState | {
|
|
9
|
+
zoomLevel: import('../../lib/index.ts').ZoomLevel;
|
|
10
|
+
currentZoomLevel: number;
|
|
11
|
+
}>;
|
|
12
|
+
provides: import('vue').Ref<Readonly<import('../../lib/index.ts').ZoomCapability> | null, Readonly<import('../../lib/index.ts').ZoomCapability> | null>;
|
|
13
|
+
};
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("vue"),t=require("@embedpdf/core/vue"),o=require("@embedpdf/plugin-zoom"),n=()=>t.useCapability(o.ZoomPlugin.id);function r({element:e,viewportProvides:t,zoomProvides:o}){if("undefined"==typeof window)return()=>{};let n,r=0,a={x:0,y:0};const l=()=>{e.style.transform="none",e.style.transformOrigin="0 0"},s=n=>{var l;r=o.getState().currentZoomLevel;const s=t.getBoundingRect();a={x:n.center.x-s.origin.x,y:n.center.y-s.origin.y};const i=e.getBoundingClientRect();e.style.transformOrigin=`${n.center.x-i.left}px ${n.center.y-i.top}px`,(null==(l=n.srcEvent)?void 0:l.cancelable)&&(n.srcEvent.preventDefault(),n.srcEvent.stopPropagation())},i=t=>{var o,n;n=t.scale,e.style.transform=`scale(${n})`,(null==(o=t.srcEvent)?void 0:o.cancelable)&&(t.srcEvent.preventDefault(),t.srcEvent.stopPropagation())},u=e=>{const t=(e.scale-1)*r;o.requestZoomBy(t,{vx:a.x,vy:a.y}),l(),r=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})();n=new t(e,{touchAction:"pan-x pan-y",inputClass:o}),n.get("pinch").set({enable:!0,pointers:2,threshold:.1}),n.on("pinchstart",s),n.on("pinchmove",i),n.on("pinchend",u)}catch(t){console.warn("Failed to load HammerJS:",t)}})(),()=>{null==n||n.destroy(),l()}}function a(){const{provides:o}=t.useCapability("viewport"),{provides:a}=n(),l=e.ref(null);let s;return e.onMounted((async()=>{const e=l.value;e&&o.value&&a.value&&(s=r({element:e,viewportProvides:o.value,zoomProvides:a.value}))})),e.onUnmounted((()=>{null==s||s()})),{elementRef:l}}const l=e.defineComponent({__name:"marquee-zoom",props:{pageIndex:{},scale:{},className:{},stroke:{default:"rgba(33,150,243,0.8)"},fill:{default:"rgba(33,150,243,0.15)"}},setup(t){const o=t,{provides:r}=n(),a=e.ref(null);let l;return e.onMounted((()=>{r.value&&(l=r.value.registerMarqueeOnPage({pageIndex:o.pageIndex,scale:o.scale,callback:{onPreview:e=>{a.value=e}}}))})),e.onUnmounted((()=>{null==l||l()})),(t,o)=>a.value?(e.openBlock(),e.createElementBlock("div",{key:0,style:e.normalizeStyle({position:"absolute",pointerEvents:"none",left:a.value.origin.x*t.scale+"px",top:a.value.origin.y*t.scale+"px",width:a.value.size.width*t.scale+"px",height:a.value.size.height*t.scale+"px",border:`1px solid ${t.stroke}`,background:t.fill,boxSizing:"border-box"}),class:e.normalizeClass(t.className)},null,6)):e.createCommentVNode("",!0)}}),s=e.defineComponent({__name:"pinch-wrapper",setup(t){const{elementRef:o}=a();return(t,n)=>(e.openBlock(),e.createElementBlock("div",e.mergeProps({ref_key:"elementRef",ref:o,style:{display:"block",width:"fit-content",overflow:"visible",boxSizing:"border-box",margin:"0px auto"}},t.$attrs),[e.renderSlot(t.$slots,"default")],16))}});exports.MarqueeZoom=l,exports.PinchWrapper=s,exports.usePinch=a,exports.useZoom=()=>{const{provides:t}=n(),r=e.ref(o.initialState);return e.onMounted((()=>{if(!t.value)return;const o=t.value.onStateChange((e=>{r.value=e}));e.onUnmounted((()=>{o()}))})),{state:r,provides:t}},exports.useZoomCapability=n,exports.useZoomPlugin=()=>t.usePlugin(o.ZoomPlugin.id),Object.keys(o).forEach((e=>{"default"===e||Object.prototype.hasOwnProperty.call(exports,e)||Object.defineProperty(exports,e,{enumerable:!0,get:()=>o[e]})}));
|
|
2
|
+
//# sourceMappingURL=index.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.cjs","sources":["../../src/vue/hooks/use-zoom.ts","../../src/shared/utils/pinch-zoom-logic.ts","../../src/vue/hooks/use-pinch-zoom.ts","../../src/vue/components/marquee-zoom.vue","../../src/vue/components/pinch-wrapper.vue"],"sourcesContent":["import { ref, onMounted, onUnmounted } from 'vue';\nimport { useCapability, usePlugin } from '@embedpdf/core/vue';\nimport { initialState, ZoomPlugin, ZoomState } from '@embedpdf/plugin-zoom';\n\nexport const useZoomCapability = () => useCapability<ZoomPlugin>(ZoomPlugin.id);\nexport const useZoomPlugin = () => usePlugin<ZoomPlugin>(ZoomPlugin.id);\n\nexport const useZoom = () => {\n const { provides } = useZoomCapability();\n const state = ref<ZoomState>(initialState);\n\n onMounted(() => {\n if (!provides.value) return;\n\n const unsubscribe = provides.value.onStateChange((newState) => {\n state.value = newState;\n });\n\n onUnmounted(() => {\n unsubscribe();\n });\n });\n\n return {\n state,\n provides,\n };\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 { ref, onMounted, onUnmounted } from 'vue';\nimport { useCapability } from '@embedpdf/core/vue';\nimport type { ViewportPlugin } from '@embedpdf/plugin-viewport';\n\nimport { setupPinchZoom } from '../../shared/utils/pinch-zoom-logic';\nimport { useZoomCapability } from './use-zoom';\n\nexport function usePinch() {\n const { provides: viewportProvides } = useCapability<ViewportPlugin>('viewport');\n const { provides: zoomProvides } = useZoomCapability();\n const elementRef = ref<HTMLDivElement | null>(null);\n\n let cleanup: (() => void) | undefined;\n\n onMounted(async () => {\n const element = elementRef.value;\n if (!element || !viewportProvides.value || !zoomProvides.value) {\n return;\n }\n\n cleanup = setupPinchZoom({\n element,\n viewportProvides: viewportProvides.value,\n zoomProvides: zoomProvides.value,\n });\n });\n\n onUnmounted(() => {\n cleanup?.();\n });\n\n return { elementRef };\n}\n","<template>\n <div\n v-if=\"rect\"\n :style=\"{\n position: 'absolute',\n pointerEvents: 'none',\n left: `${rect.origin.x * scale}px`,\n top: `${rect.origin.y * scale}px`,\n width: `${rect.size.width * scale}px`,\n height: `${rect.size.height * scale}px`,\n border: `1px solid ${stroke}`,\n background: fill,\n boxSizing: 'border-box',\n }\"\n :class=\"className\"\n />\n</template>\n\n<script setup lang=\"ts\">\nimport { ref, onMounted, onUnmounted } from 'vue';\nimport type { Rect } from '@embedpdf/models';\nimport { useZoomCapability } from '../hooks';\n\ninterface 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 className?: string;\n /** Stroke / fill colours (defaults below) */\n stroke?: string;\n fill?: string;\n}\n\nconst props = withDefaults(defineProps<MarqueeZoomProps>(), {\n stroke: 'rgba(33,150,243,0.8)',\n fill: 'rgba(33,150,243,0.15)',\n});\n\nconst { provides: zoomPlugin } = useZoomCapability();\nconst rect = ref<Rect | null>(null);\n\nlet unregister: (() => void) | undefined;\n\nonMounted(() => {\n if (!zoomPlugin.value) return;\n\n unregister = zoomPlugin.value.registerMarqueeOnPage({\n pageIndex: props.pageIndex,\n scale: props.scale,\n callback: {\n onPreview: (newRect) => {\n rect.value = newRect;\n },\n },\n });\n});\n\nonUnmounted(() => {\n unregister?.();\n});\n</script>\n","<template>\n <div\n ref=\"elementRef\"\n :style=\"{\n display: 'block',\n width: 'fit-content',\n overflow: 'visible',\n boxSizing: 'border-box',\n margin: '0px auto',\n }\"\n v-bind=\"$attrs\"\n >\n <slot />\n </div>\n</template>\n\n<script setup lang=\"ts\">\nimport { usePinch } from '../hooks/use-pinch-zoom';\n\nconst { elementRef } = usePinch();\n</script>\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","provides","elementRef","ref","cleanup","onMounted","value","onUnmounted","props","__props","zoomPlugin","rect","unregister","registerMarqueeOnPage","pageIndex","callback","onPreview","newRect","_createElementBlock","_normalizeStyle","width","size","height","stroke","fill","class","className","_openBlock","_mergeProps","$attrs","_renderSlot","_ctx","$slots","state","initialState","unsubscribe","onStateChange","newState","usePlugin"],"mappings":"0KAIaA,EAAoB,IAAMC,gBAA0BC,EAAAA,WAAWC,ICKrE,SAASC,GAAeC,QAAEA,EAASC,iBAAAA,EAAAC,aAAkBA,IAEtD,GAAkB,oBAAXC,OACT,MAAO,OAGL,IAAAC,EACAC,EAAc,EACdC,EAAa,CAAEC,EAAG,EAAGC,EAAG,GAEtB,MAOAC,EAAiB,KACrBT,EAAQU,MAAMC,UAAY,OAC1BX,EAAQU,MAAME,gBAAkB,KAAA,EAG5BC,EAAcC,UAClBT,EAbgCH,EAAaa,WAapBC,iBAEnB,MAAAC,EAAWhB,EAAiBiB,kBAErBZ,EAAA,CACXC,EAAGO,EAAEK,OAAOZ,EAAIU,EAASG,OAAOb,EAChCC,EAAGM,EAAEK,OAAOX,EAAIS,EAASG,OAAOZ,GAI5B,MAAAa,EAAYrB,EAAQsB,wBAC1BtB,EAAQU,MAAME,gBAAkB,GAAGE,EAAEK,OAAOZ,EAAIc,EAAUE,UAAUT,EAAEK,OAAOX,EAAIa,EAAUG,SAGvF,OAAAC,EAAAX,EAAEY,eAAF,EAAAD,EAAYE,cACdb,EAAEY,SAASE,iBACXd,EAAEY,SAASG,kBAAgB,EAIzBC,EAAahB,UA/BMiB,IAgCPjB,EAAEiB,MA9BV/B,EAAAU,MAAMC,UAAY,SAASoB,MA+B/B,OAAAN,EAAAX,EAAEY,eAAF,EAAAD,EAAYE,cACdb,EAAEY,SAASE,iBACXd,EAAEY,SAASG,kBAAgB,EAIzBG,EAAYlB,IAEV,MAAAmB,GAASnB,EAAEiB,MAAQ,GAAK1B,EACjBH,EAAAgC,cAAcD,EAAO,CAAEE,GAAI7B,EAAWC,EAAG6B,GAAI9B,EAAWE,IAEtDC,IACDJ,EAAA,CAAA,EAsChB,MAlCoBgC,WACd,IACF,MAAMC,SAAgBC,QAAOC,UAAAC,MAAA,IAAAC,QAAA,4BAAaD,MAAAE,GAAAA,EAAAvC,UAAAwC,QAKpCC,QACJ,MACMC,EAAgB,iBAAkB3C,QAAU4C,UAAUC,eAAiB,EAEzE,OADuBF,GAFN,wCAEoCG,KAAKF,UAAUG,WACzCZ,EAAOa,WACjCL,EACER,EAAOc,gBADad,EAAOe,UAEjC,KAEMjD,EAAA,IAAIkC,EAAOtC,EAAS,CAC3BsD,YAAa,cACbT,eAGKzC,EAAAmD,IAAI,SAASC,IAAI,CAAEC,QAAQ,EAAMC,SAAU,EAAGC,UAAW,KAEzDvD,EAAAwD,GAAG,aAAc/C,GACjBT,EAAAwD,GAAG,YAAa9B,GAChB1B,EAAAwD,GAAG,WAAY5B,SACf6B,GACCC,QAAAC,KAAK,2BAA4BF,EAAK,GAItCG,GAGL,KACG,MAAA5D,GAAAA,EAAA6D,UACOxD,GAAA,CAEnB,CCrGO,SAASyD,IACd,MAAQC,SAAUlE,GAAqBL,EAAAA,cAA8B,aAC7DuE,SAAUjE,GAAiBP,IAC7ByE,EAAaC,MAA2B,MAE1C,IAAAC,EAmBJ,OAjBAC,EAAAA,WAAUlC,UACR,MAAMrC,EAAUoE,EAAWI,MACtBxE,GAAYC,EAAiBuE,OAAUtE,EAAasE,QAIzDF,EAAUvE,EAAe,CACvBC,UACAC,iBAAkBA,EAAiBuE,MACnCtE,aAAcA,EAAasE,QAC5B,IAGHC,EAAAA,aAAY,KACA,MAAAH,GAAAA,GAAA,IAGL,CAAEF,aACX,qLCGA,MAAMM,EAAQC,GAKNR,SAAUS,GAAejF,IAC3BkF,EAAOR,MAAiB,MAE1B,IAAAS,SAEJP,EAAAA,WAAU,KACHK,EAAWJ,QAEHM,EAAAF,EAAWJ,MAAMO,sBAAsB,CAClDC,UAAWN,EAAMM,UACjBjD,MAAO2C,EAAM3C,MACbkD,SAAU,CACRC,UAAYC,IACVN,EAAKL,MAAQW,CAAA,KAGlB,IAGHV,EAAAA,aAAY,KACG,MAAAK,GAAAA,GAAA,WA1DLD,EAAIL,qBADZY,EAAAA,mBAcE,MAAA,OAZC1E,MAAK2E,EAAAA,eAAA,0CAA4E9D,KAAAsD,EAAAL,MAAKpD,OAAOb,EAAIwB,EAAKA,MAArB,KAAyCP,IAAAqD,EAAAL,MAAKpD,OAAOZ,EAAIuB,EAAKA,MAArB,KAA2CuD,MAAAT,EAAAL,MAAKe,KAAKD,MAAQvD,EAAKA,MAAvB,KAA8CyD,OAAAX,EAAAL,MAAKe,KAAKC,OAASzD,EAAKA,MAAxB,yBAAyD0D,EAAMA,oBAAsBC,EAAIA,8BAW5SC,uBAAOC,EAASA,yGCKf,MAAAxB,WAAEA,GAAeF,kBAlBrB2B,cAAAT,qBAYM,MAZNU,EAAAA,WAYM,SAXA,aAAJzB,IAAID,EACH1D,MAAO,mGAOAqF,EAAMA,QAAA,CAEdC,aAAQC,EAAAC,OAAA,oGJLW,KACf,MAAA/B,SAAEA,GAAaxE,IACfwG,EAAQ9B,MAAe+B,gBActB,OAZP7B,EAAAA,WAAU,KACJ,IAACJ,EAASK,MAAO,OAErB,MAAM6B,EAAclC,EAASK,MAAM8B,eAAeC,IAChDJ,EAAM3B,MAAQ+B,CAAA,IAGhB9B,EAAAA,aAAY,KACE4B,GAAA,GACb,IAGI,CACLF,QACAhC,WACF,oDArB2B,IAAMqC,YAAsB3G,EAAAA,WAAWC"}
|
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
import { ref, onMounted, onUnmounted, defineComponent, createElementBlock, createCommentVNode, openBlock, normalizeClass, normalizeStyle, mergeProps, renderSlot } from "vue";
|
|
2
|
+
import { useCapability, usePlugin } from "@embedpdf/core/vue";
|
|
3
|
+
import { ZoomPlugin, initialState } from "@embedpdf/plugin-zoom";
|
|
4
|
+
export * from "@embedpdf/plugin-zoom";
|
|
5
|
+
const useZoomCapability = () => useCapability(ZoomPlugin.id);
|
|
6
|
+
const useZoomPlugin = () => usePlugin(ZoomPlugin.id);
|
|
7
|
+
const useZoom = () => {
|
|
8
|
+
const { provides } = useZoomCapability();
|
|
9
|
+
const state = ref(initialState);
|
|
10
|
+
onMounted(() => {
|
|
11
|
+
if (!provides.value) return;
|
|
12
|
+
const unsubscribe = provides.value.onStateChange((newState) => {
|
|
13
|
+
state.value = newState;
|
|
14
|
+
});
|
|
15
|
+
onUnmounted(() => {
|
|
16
|
+
unsubscribe();
|
|
17
|
+
});
|
|
18
|
+
});
|
|
19
|
+
return {
|
|
20
|
+
state,
|
|
21
|
+
provides
|
|
22
|
+
};
|
|
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();
|
|
53
|
+
}
|
|
54
|
+
};
|
|
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
|
+
}
|
|
99
|
+
function usePinch() {
|
|
100
|
+
const { provides: viewportProvides } = useCapability("viewport");
|
|
101
|
+
const { provides: zoomProvides } = useZoomCapability();
|
|
102
|
+
const elementRef = ref(null);
|
|
103
|
+
let cleanup;
|
|
104
|
+
onMounted(async () => {
|
|
105
|
+
const element = elementRef.value;
|
|
106
|
+
if (!element || !viewportProvides.value || !zoomProvides.value) {
|
|
107
|
+
return;
|
|
108
|
+
}
|
|
109
|
+
cleanup = setupPinchZoom({
|
|
110
|
+
element,
|
|
111
|
+
viewportProvides: viewportProvides.value,
|
|
112
|
+
zoomProvides: zoomProvides.value
|
|
113
|
+
});
|
|
114
|
+
});
|
|
115
|
+
onUnmounted(() => {
|
|
116
|
+
cleanup == null ? void 0 : cleanup();
|
|
117
|
+
});
|
|
118
|
+
return { elementRef };
|
|
119
|
+
}
|
|
120
|
+
const _sfc_main$1 = /* @__PURE__ */ defineComponent({
|
|
121
|
+
__name: "marquee-zoom",
|
|
122
|
+
props: {
|
|
123
|
+
pageIndex: {},
|
|
124
|
+
scale: {},
|
|
125
|
+
className: {},
|
|
126
|
+
stroke: { default: "rgba(33,150,243,0.8)" },
|
|
127
|
+
fill: { default: "rgba(33,150,243,0.15)" }
|
|
128
|
+
},
|
|
129
|
+
setup(__props) {
|
|
130
|
+
const props = __props;
|
|
131
|
+
const { provides: zoomPlugin } = useZoomCapability();
|
|
132
|
+
const rect = ref(null);
|
|
133
|
+
let unregister;
|
|
134
|
+
onMounted(() => {
|
|
135
|
+
if (!zoomPlugin.value) return;
|
|
136
|
+
unregister = zoomPlugin.value.registerMarqueeOnPage({
|
|
137
|
+
pageIndex: props.pageIndex,
|
|
138
|
+
scale: props.scale,
|
|
139
|
+
callback: {
|
|
140
|
+
onPreview: (newRect) => {
|
|
141
|
+
rect.value = newRect;
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
});
|
|
145
|
+
});
|
|
146
|
+
onUnmounted(() => {
|
|
147
|
+
unregister == null ? void 0 : unregister();
|
|
148
|
+
});
|
|
149
|
+
return (_ctx, _cache) => {
|
|
150
|
+
return rect.value ? (openBlock(), createElementBlock("div", {
|
|
151
|
+
key: 0,
|
|
152
|
+
style: normalizeStyle({
|
|
153
|
+
position: "absolute",
|
|
154
|
+
pointerEvents: "none",
|
|
155
|
+
left: `${rect.value.origin.x * _ctx.scale}px`,
|
|
156
|
+
top: `${rect.value.origin.y * _ctx.scale}px`,
|
|
157
|
+
width: `${rect.value.size.width * _ctx.scale}px`,
|
|
158
|
+
height: `${rect.value.size.height * _ctx.scale}px`,
|
|
159
|
+
border: `1px solid ${_ctx.stroke}`,
|
|
160
|
+
background: _ctx.fill,
|
|
161
|
+
boxSizing: "border-box"
|
|
162
|
+
}),
|
|
163
|
+
class: normalizeClass(_ctx.className)
|
|
164
|
+
}, null, 6)) : createCommentVNode("", true);
|
|
165
|
+
};
|
|
166
|
+
}
|
|
167
|
+
});
|
|
168
|
+
const _sfc_main = /* @__PURE__ */ defineComponent({
|
|
169
|
+
__name: "pinch-wrapper",
|
|
170
|
+
setup(__props) {
|
|
171
|
+
const { elementRef } = usePinch();
|
|
172
|
+
return (_ctx, _cache) => {
|
|
173
|
+
return openBlock(), createElementBlock("div", mergeProps({
|
|
174
|
+
ref_key: "elementRef",
|
|
175
|
+
ref: elementRef,
|
|
176
|
+
style: {
|
|
177
|
+
display: "block",
|
|
178
|
+
width: "fit-content",
|
|
179
|
+
overflow: "visible",
|
|
180
|
+
boxSizing: "border-box",
|
|
181
|
+
margin: "0px auto"
|
|
182
|
+
}
|
|
183
|
+
}, _ctx.$attrs), [
|
|
184
|
+
renderSlot(_ctx.$slots, "default")
|
|
185
|
+
], 16);
|
|
186
|
+
};
|
|
187
|
+
}
|
|
188
|
+
});
|
|
189
|
+
export {
|
|
190
|
+
_sfc_main$1 as MarqueeZoom,
|
|
191
|
+
_sfc_main as PinchWrapper,
|
|
192
|
+
usePinch,
|
|
193
|
+
useZoom,
|
|
194
|
+
useZoomCapability,
|
|
195
|
+
useZoomPlugin
|
|
196
|
+
};
|
|
197
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sources":["../../src/vue/hooks/use-zoom.ts","../../src/shared/utils/pinch-zoom-logic.ts","../../src/vue/hooks/use-pinch-zoom.ts","../../src/vue/components/marquee-zoom.vue","../../src/vue/components/pinch-wrapper.vue"],"sourcesContent":["import { ref, onMounted, onUnmounted } from 'vue';\nimport { useCapability, usePlugin } from '@embedpdf/core/vue';\nimport { initialState, ZoomPlugin, ZoomState } from '@embedpdf/plugin-zoom';\n\nexport const useZoomCapability = () => useCapability<ZoomPlugin>(ZoomPlugin.id);\nexport const useZoomPlugin = () => usePlugin<ZoomPlugin>(ZoomPlugin.id);\n\nexport const useZoom = () => {\n const { provides } = useZoomCapability();\n const state = ref<ZoomState>(initialState);\n\n onMounted(() => {\n if (!provides.value) return;\n\n const unsubscribe = provides.value.onStateChange((newState) => {\n state.value = newState;\n });\n\n onUnmounted(() => {\n unsubscribe();\n });\n });\n\n return {\n state,\n provides,\n };\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 { ref, onMounted, onUnmounted } from 'vue';\nimport { useCapability } from '@embedpdf/core/vue';\nimport type { ViewportPlugin } from '@embedpdf/plugin-viewport';\n\nimport { setupPinchZoom } from '../../shared/utils/pinch-zoom-logic';\nimport { useZoomCapability } from './use-zoom';\n\nexport function usePinch() {\n const { provides: viewportProvides } = useCapability<ViewportPlugin>('viewport');\n const { provides: zoomProvides } = useZoomCapability();\n const elementRef = ref<HTMLDivElement | null>(null);\n\n let cleanup: (() => void) | undefined;\n\n onMounted(async () => {\n const element = elementRef.value;\n if (!element || !viewportProvides.value || !zoomProvides.value) {\n return;\n }\n\n cleanup = setupPinchZoom({\n element,\n viewportProvides: viewportProvides.value,\n zoomProvides: zoomProvides.value,\n });\n });\n\n onUnmounted(() => {\n cleanup?.();\n });\n\n return { elementRef };\n}\n","<template>\n <div\n v-if=\"rect\"\n :style=\"{\n position: 'absolute',\n pointerEvents: 'none',\n left: `${rect.origin.x * scale}px`,\n top: `${rect.origin.y * scale}px`,\n width: `${rect.size.width * scale}px`,\n height: `${rect.size.height * scale}px`,\n border: `1px solid ${stroke}`,\n background: fill,\n boxSizing: 'border-box',\n }\"\n :class=\"className\"\n />\n</template>\n\n<script setup lang=\"ts\">\nimport { ref, onMounted, onUnmounted } from 'vue';\nimport type { Rect } from '@embedpdf/models';\nimport { useZoomCapability } from '../hooks';\n\ninterface 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 className?: string;\n /** Stroke / fill colours (defaults below) */\n stroke?: string;\n fill?: string;\n}\n\nconst props = withDefaults(defineProps<MarqueeZoomProps>(), {\n stroke: 'rgba(33,150,243,0.8)',\n fill: 'rgba(33,150,243,0.15)',\n});\n\nconst { provides: zoomPlugin } = useZoomCapability();\nconst rect = ref<Rect | null>(null);\n\nlet unregister: (() => void) | undefined;\n\nonMounted(() => {\n if (!zoomPlugin.value) return;\n\n unregister = zoomPlugin.value.registerMarqueeOnPage({\n pageIndex: props.pageIndex,\n scale: props.scale,\n callback: {\n onPreview: (newRect) => {\n rect.value = newRect;\n },\n },\n });\n});\n\nonUnmounted(() => {\n unregister?.();\n});\n</script>\n","<template>\n <div\n ref=\"elementRef\"\n :style=\"{\n display: 'block',\n width: 'fit-content',\n overflow: 'visible',\n boxSizing: 'border-box',\n margin: '0px auto',\n }\"\n v-bind=\"$attrs\"\n >\n <slot />\n </div>\n</template>\n\n<script setup lang=\"ts\">\nimport { usePinch } from '../hooks/use-pinch-zoom';\n\nconst { elementRef } = usePinch();\n</script>\n"],"names":["_createElementBlock","_normalizeStyle","scale","stroke","fill","className","_openBlock","_mergeProps","$attrs","_renderSlot"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@embedpdf/plugin-zoom",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.21",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"main": "./dist/index.cjs",
|
|
6
6
|
"module": "./dist/index.js",
|
|
@@ -20,30 +20,36 @@
|
|
|
20
20
|
"types": "./dist/react/index.d.ts",
|
|
21
21
|
"import": "./dist/react/index.js",
|
|
22
22
|
"require": "./dist/react/index.cjs"
|
|
23
|
+
},
|
|
24
|
+
"./vue": {
|
|
25
|
+
"types": "./dist/vue/index.d.ts",
|
|
26
|
+
"import": "./dist/vue/index.js",
|
|
27
|
+
"require": "./dist/vue/index.cjs"
|
|
23
28
|
}
|
|
24
29
|
},
|
|
25
30
|
"dependencies": {
|
|
26
31
|
"hammerjs": "^2.0.8",
|
|
27
|
-
"@embedpdf/models": "1.0.
|
|
32
|
+
"@embedpdf/models": "1.0.21"
|
|
28
33
|
},
|
|
29
34
|
"devDependencies": {
|
|
30
35
|
"@types/hammerjs": "^2.0.46",
|
|
31
36
|
"@types/react": "^18.2.0",
|
|
32
37
|
"typescript": "^5.0.0",
|
|
33
|
-
"@embedpdf/core": "1.0.
|
|
34
|
-
"@embedpdf/plugin-viewport": "1.0.20",
|
|
35
|
-
"@embedpdf/plugin-interaction-manager": "1.0.20",
|
|
38
|
+
"@embedpdf/core": "1.0.21",
|
|
36
39
|
"@embedpdf/build": "1.0.0",
|
|
37
|
-
"@embedpdf/plugin-scroll": "1.0.
|
|
40
|
+
"@embedpdf/plugin-scroll": "1.0.21",
|
|
41
|
+
"@embedpdf/plugin-interaction-manager": "1.0.21",
|
|
42
|
+
"@embedpdf/plugin-viewport": "1.0.21"
|
|
38
43
|
},
|
|
39
44
|
"peerDependencies": {
|
|
40
45
|
"react": ">=16.8.0",
|
|
41
46
|
"react-dom": ">=16.8.0",
|
|
42
47
|
"preact": "^10.26.4",
|
|
43
|
-
"
|
|
44
|
-
"@embedpdf/plugin-viewport": "1.0.
|
|
45
|
-
"@embedpdf/plugin-scroll": "1.0.
|
|
46
|
-
"@embedpdf/
|
|
48
|
+
"vue": ">=3.2.0",
|
|
49
|
+
"@embedpdf/plugin-viewport": "1.0.21",
|
|
50
|
+
"@embedpdf/plugin-scroll": "1.0.21",
|
|
51
|
+
"@embedpdf/core": "1.0.21",
|
|
52
|
+
"@embedpdf/plugin-interaction-manager": "1.0.21"
|
|
47
53
|
},
|
|
48
54
|
"files": [
|
|
49
55
|
"dist",
|
|
@@ -65,7 +71,8 @@
|
|
|
65
71
|
"build:base": "vite build --mode base",
|
|
66
72
|
"build:react": "vite build --mode react",
|
|
67
73
|
"build:preact": "vite build --mode preact",
|
|
68
|
-
"build": "
|
|
74
|
+
"build:vue": "vite build --mode vue",
|
|
75
|
+
"build": "pnpm run clean && concurrently -c auto -n base,react,preact,vue \"vite build --mode base\" \"vite build --mode react\" \"vite build --mode preact\" \"vite build --mode vue\"",
|
|
69
76
|
"clean": "rimraf dist",
|
|
70
77
|
"lint": "eslint src --color",
|
|
71
78
|
"lint:fix": "eslint src --color --fix"
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export * from '@embedpdf/plugin-interaction-manager/preact';
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export * from '@embedpdf/plugin-interaction-manager/react';
|