@embedpdf/plugin-zoom 1.0.10 → 1.0.12
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/hammer-Bs-QCG8V.cjs +7 -0
- package/dist/hammer-Bs-QCG8V.cjs.map +1 -0
- package/dist/hammer-e1aXHboh.js +1810 -0
- package/dist/hammer-e1aXHboh.js.map +1 -0
- package/dist/index.cjs +2 -481
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +1 -147
- package/dist/index.js +43 -59
- package/dist/index.js.map +1 -1
- package/dist/lib/actions.d.ts +20 -0
- package/dist/lib/index.d.ts +10 -0
- package/dist/lib/manifest.d.ts +4 -0
- package/dist/lib/reducer.d.ts +5 -0
- package/dist/lib/types.d.ts +84 -0
- package/dist/lib/zoom-plugin.d.ts +38 -0
- package/dist/preact/adapter.d.ts +5 -0
- package/dist/preact/core.d.ts +1 -0
- package/dist/preact/index.cjs +2 -262
- package/dist/preact/index.cjs.map +1 -1
- package/dist/preact/index.d.ts +1 -54
- package/dist/preact/index.js +29 -34
- package/dist/preact/index.js.map +1 -1
- package/dist/preact/interaction-manager.d.ts +1 -0
- package/dist/react/adapter.d.ts +2 -0
- package/dist/react/core.d.ts +1 -0
- package/dist/react/index.cjs +2 -262
- package/dist/react/index.cjs.map +1 -1
- package/dist/react/index.d.ts +1 -53
- package/dist/react/index.js +28 -34
- package/dist/react/index.js.map +1 -1
- package/dist/react/interaction-manager.d.ts +1 -0
- package/dist/shared-preact/components/index.d.ts +2 -0
- package/dist/shared-preact/components/marquee-zoom.d.ts +21 -0
- package/dist/shared-preact/components/pinch-wrapper.d.ts +7 -0
- package/dist/shared-preact/hooks/index.d.ts +2 -0
- package/dist/shared-preact/hooks/use-pinch-zoom.d.ts +3 -0
- package/dist/shared-preact/hooks/use-zoom.d.ts +15 -0
- package/dist/shared-preact/index.d.ts +2 -0
- package/dist/shared-react/components/index.d.ts +2 -0
- package/dist/shared-react/components/marquee-zoom.d.ts +21 -0
- package/dist/shared-react/components/pinch-wrapper.d.ts +7 -0
- package/dist/shared-react/hooks/index.d.ts +2 -0
- package/dist/shared-react/hooks/use-pinch-zoom.d.ts +3 -0
- package/dist/shared-react/hooks/use-zoom.d.ts +15 -0
- package/dist/shared-react/index.d.ts +2 -0
- package/package.json +18 -17
- package/dist/index.d.cts +0 -147
- package/dist/preact/index.d.cts +0 -54
- package/dist/react/index.d.cts +0 -53
package/dist/preact/index.js
CHANGED
|
@@ -1,14 +1,16 @@
|
|
|
1
|
-
// src/preact/hooks/use-zoom.ts
|
|
2
1
|
import { useCapability, usePlugin } from "@embedpdf/core/preact";
|
|
3
|
-
import {
|
|
4
|
-
import
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
2
|
+
import { ZoomPlugin, initialState } from "@embedpdf/plugin-zoom";
|
|
3
|
+
import "preact";
|
|
4
|
+
import { useState, useEffect, useRef, useMemo } from "preact/hooks";
|
|
5
|
+
import { jsx } from "preact/jsx-runtime";
|
|
6
|
+
import { usePointerHandlers } from "@embedpdf/plugin-interaction-manager/preact";
|
|
7
|
+
const useZoomCapability = () => useCapability(ZoomPlugin.id);
|
|
8
|
+
const useZoomPlugin = () => usePlugin(ZoomPlugin.id);
|
|
9
|
+
const useZoom = () => {
|
|
8
10
|
const { provides } = useZoomCapability();
|
|
9
11
|
const [state, setState] = useState(initialState);
|
|
10
12
|
useEffect(() => {
|
|
11
|
-
return provides
|
|
13
|
+
return provides == null ? void 0 : provides.onStateChange((action) => {
|
|
12
14
|
setState(action);
|
|
13
15
|
});
|
|
14
16
|
}, [provides]);
|
|
@@ -17,15 +19,11 @@ var useZoom = () => {
|
|
|
17
19
|
provides
|
|
18
20
|
};
|
|
19
21
|
};
|
|
20
|
-
|
|
21
|
-
// src/preact/hooks/use-pinch-zoom.ts
|
|
22
|
-
import { useEffect as useEffect2, useRef } from "preact/hooks";
|
|
23
|
-
import { useCapability as useCapability2 } from "@embedpdf/core/preact";
|
|
24
22
|
function usePinch() {
|
|
25
|
-
const { provides: viewportProvides } =
|
|
23
|
+
const { provides: viewportProvides } = useCapability("viewport");
|
|
26
24
|
const { provides: zoomProvides } = useZoomCapability();
|
|
27
25
|
const elementRef = useRef(null);
|
|
28
|
-
|
|
26
|
+
useEffect(() => {
|
|
29
27
|
const element = elementRef.current;
|
|
30
28
|
if (!element || !viewportProvides || !zoomProvides) {
|
|
31
29
|
return;
|
|
@@ -45,6 +43,7 @@ function usePinch() {
|
|
|
45
43
|
element.style.transformOrigin = "0 0";
|
|
46
44
|
};
|
|
47
45
|
const pinchStart = (e) => {
|
|
46
|
+
var _a;
|
|
48
47
|
initialZoom = getState().currentZoomLevel;
|
|
49
48
|
const contRect = viewportProvides.getBoundingRect();
|
|
50
49
|
lastCenter = {
|
|
@@ -53,14 +52,15 @@ function usePinch() {
|
|
|
53
52
|
};
|
|
54
53
|
const innerRect = element.getBoundingClientRect();
|
|
55
54
|
element.style.transformOrigin = `${e.center.x - innerRect.left}px ${e.center.y - innerRect.top}px`;
|
|
56
|
-
if (e.srcEvent
|
|
55
|
+
if ((_a = e.srcEvent) == null ? void 0 : _a.cancelable) {
|
|
57
56
|
e.srcEvent.preventDefault();
|
|
58
57
|
e.srcEvent.stopPropagation();
|
|
59
58
|
}
|
|
60
59
|
};
|
|
61
60
|
const pinchMove = (e) => {
|
|
61
|
+
var _a;
|
|
62
62
|
updateTransform(e.scale);
|
|
63
|
-
if (e.srcEvent
|
|
63
|
+
if ((_a = e.srcEvent) == null ? void 0 : _a.cancelable) {
|
|
64
64
|
e.srcEvent.preventDefault();
|
|
65
65
|
e.srcEvent.stopPropagation();
|
|
66
66
|
}
|
|
@@ -73,7 +73,7 @@ function usePinch() {
|
|
|
73
73
|
};
|
|
74
74
|
const setupHammer = async () => {
|
|
75
75
|
try {
|
|
76
|
-
const Hammer = (await import("
|
|
76
|
+
const Hammer = (await import("../hammer-e1aXHboh.js").then((n) => n.h)).default;
|
|
77
77
|
const inputClass = (() => {
|
|
78
78
|
const MOBILE_REGEX = /mobile|tablet|ip(ad|hone|od)|android/i;
|
|
79
79
|
const SUPPORT_TOUCH = "ontouchstart" in window || navigator.maxTouchPoints > 0;
|
|
@@ -97,15 +97,12 @@ function usePinch() {
|
|
|
97
97
|
};
|
|
98
98
|
setupHammer();
|
|
99
99
|
return () => {
|
|
100
|
-
hammer
|
|
100
|
+
hammer == null ? void 0 : hammer.destroy();
|
|
101
101
|
resetTransform();
|
|
102
102
|
};
|
|
103
103
|
}, [viewportProvides, zoomProvides]);
|
|
104
104
|
return { elementRef };
|
|
105
105
|
}
|
|
106
|
-
|
|
107
|
-
// src/preact/components/pinch-wrapper.tsx
|
|
108
|
-
import { jsx } from "preact/jsx-runtime";
|
|
109
106
|
function PinchWrapper({ children, style, ...props }) {
|
|
110
107
|
const { elementRef } = usePinch();
|
|
111
108
|
return /* @__PURE__ */ jsx(
|
|
@@ -125,12 +122,7 @@ function PinchWrapper({ children, style, ...props }) {
|
|
|
125
122
|
}
|
|
126
123
|
);
|
|
127
124
|
}
|
|
128
|
-
|
|
129
|
-
// src/preact/components/marquee-zoom.tsx
|
|
130
|
-
import { useEffect as useEffect3, useMemo, useRef as useRef2, useState as useState2 } from "preact/hooks";
|
|
131
|
-
import { usePointerHandlers } from "@embedpdf/plugin-interaction-manager/preact";
|
|
132
|
-
import { jsx as jsx2 } from "preact/jsx-runtime";
|
|
133
|
-
var MarqueeZoom = ({
|
|
125
|
+
const MarqueeZoom = ({
|
|
134
126
|
pageIndex,
|
|
135
127
|
scale,
|
|
136
128
|
pageWidth,
|
|
@@ -142,16 +134,17 @@ var MarqueeZoom = ({
|
|
|
142
134
|
const { provides: zoom } = useZoomCapability();
|
|
143
135
|
const { register } = usePointerHandlers({ modeId: "marqueeZoom", pageIndex });
|
|
144
136
|
const clamp = (v, min, max) => Math.max(min, Math.min(max, v));
|
|
145
|
-
const startRef =
|
|
146
|
-
const [rect, setRect] =
|
|
137
|
+
const startRef = useRef(null);
|
|
138
|
+
const [rect, setRect] = useState(null);
|
|
147
139
|
const pageWidthPDF = pageWidth / scale;
|
|
148
140
|
const pageHeightPDF = pageHeight / scale;
|
|
149
141
|
const handlers = useMemo(
|
|
150
142
|
() => ({
|
|
151
143
|
onPointerDown: (pos, evt) => {
|
|
144
|
+
var _a, _b;
|
|
152
145
|
startRef.current = pos;
|
|
153
146
|
setRect({ origin: { x: pos.x, y: pos.y }, size: { width: 0, height: 0 } });
|
|
154
|
-
evt.target
|
|
147
|
+
(_b = (_a = evt.target) == null ? void 0 : _a.setPointerCapture) == null ? void 0 : _b.call(_a, evt.pointerId);
|
|
155
148
|
},
|
|
156
149
|
onPointerMove: (pos) => {
|
|
157
150
|
if (!startRef.current) return;
|
|
@@ -165,6 +158,7 @@ var MarqueeZoom = ({
|
|
|
165
158
|
setRect({ origin: { x: left, y: top }, size: { width, height } });
|
|
166
159
|
},
|
|
167
160
|
onPointerUp: (_, evt) => {
|
|
161
|
+
var _a, _b;
|
|
168
162
|
if (rect && zoom) {
|
|
169
163
|
const dragPx = Math.max(rect.size.width, rect.size.height) * scale;
|
|
170
164
|
if (dragPx > 5) {
|
|
@@ -175,22 +169,23 @@ var MarqueeZoom = ({
|
|
|
175
169
|
}
|
|
176
170
|
startRef.current = null;
|
|
177
171
|
setRect(null);
|
|
178
|
-
evt.target
|
|
172
|
+
(_b = (_a = evt.target) == null ? void 0 : _a.releasePointerCapture) == null ? void 0 : _b.call(_a, evt.pointerId);
|
|
179
173
|
},
|
|
180
174
|
onPointerCancel: (_, evt) => {
|
|
175
|
+
var _a, _b;
|
|
181
176
|
startRef.current = null;
|
|
182
177
|
setRect(null);
|
|
183
|
-
evt.target
|
|
178
|
+
(_b = (_a = evt.target) == null ? void 0 : _a.releasePointerCapture) == null ? void 0 : _b.call(_a, evt.pointerId);
|
|
184
179
|
}
|
|
185
180
|
}),
|
|
186
181
|
[pageWidthPDF, pageWidthPDF, zoom, scale, rect, pageIndex]
|
|
187
182
|
);
|
|
188
|
-
|
|
183
|
+
useEffect(() => {
|
|
189
184
|
if (!register) return;
|
|
190
185
|
return register(handlers);
|
|
191
186
|
}, [register, handlers]);
|
|
192
187
|
if (!rect) return null;
|
|
193
|
-
return /* @__PURE__ */
|
|
188
|
+
return /* @__PURE__ */ jsx(
|
|
194
189
|
"div",
|
|
195
190
|
{
|
|
196
191
|
style: {
|
|
@@ -217,4 +212,4 @@ export {
|
|
|
217
212
|
useZoomCapability,
|
|
218
213
|
useZoomPlugin
|
|
219
214
|
};
|
|
220
|
-
//# sourceMappingURL=index.js.map
|
|
215
|
+
//# sourceMappingURL=index.js.map
|
package/dist/preact/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/preact/hooks/use-zoom.ts","../../src/preact/hooks/use-pinch-zoom.ts","../../src/preact/components/pinch-wrapper.tsx","../../src/preact/components/marquee-zoom.tsx"],"sourcesContent":["import { useCapability, usePlugin } from '@embedpdf/core/preact';\nimport { initialState, ZoomPlugin, ZoomState } from '@embedpdf/plugin-zoom';\nimport { useEffect, useState } from 'preact/hooks';\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 'preact/hooks';\nimport { useCapability } from '@embedpdf/core/preact';\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","/** @jsxImportSource preact */\nimport { ComponentChildren, JSX } from 'preact';\n\nimport { usePinch } from '../hooks';\n\ntype PinchWrapperProps = Omit<JSX.HTMLAttributes<HTMLDivElement>, 'style'> & {\n children: ComponentChildren;\n style?: JSX.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","/** @jsxImportSource preact */\nimport { useEffect, useMemo, useRef, useState } from 'preact/hooks';\nimport type { PointerEventHandlers } from '@embedpdf/plugin-interaction-manager';\nimport { usePointerHandlers } from '@embedpdf/plugin-interaction-manager/preact';\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 /** Width of the page */\n pageWidth: number;\n /** Height of the page */\n pageHeight: 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\n/**\n * Draws a marquee rectangle while the user drags.\n * Hook it into the interaction-manager with modeId = 'marqueeZoom'.\n */\nexport const MarqueeZoom = ({\n pageIndex,\n scale,\n pageWidth,\n pageHeight,\n className,\n stroke = 'rgba(33,150,243,0.8)',\n fill = 'rgba(33,150,243,0.15)',\n}: MarqueeZoomProps) => {\n /* ------------------------------------------------------------------ */\n /* zoom capability */\n /* ------------------------------------------------------------------ */\n const { provides: zoom } = useZoomCapability();\n\n /* ------------------------------------------------------------------ */\n /* integration with interaction-manager */\n /* ------------------------------------------------------------------ */\n const { register } = usePointerHandlers({ modeId: 'marqueeZoom', pageIndex });\n\n /* ------------------------------------------------------------------ */\n /* helpers */\n /* ------------------------------------------------------------------ */\n const clamp = (v: number, min: number, max: number) => Math.max(min, Math.min(max, v));\n\n /* ------------------------------------------------------------------ */\n /* local state – start / current drag position */\n /* ------------------------------------------------------------------ */\n const startRef = useRef<{ x: number; y: number } | null>(null);\n const [rect, setRect] = useState<Rect | null>(null);\n\n /* page size in **PDF-space** (unscaled) ----------------------------- */\n const pageWidthPDF = pageWidth / scale;\n const pageHeightPDF = pageHeight / scale;\n\n /* ------------------------------------------------------------------ */\n /* pointer handlers */\n /* ------------------------------------------------------------------ */\n const handlers = useMemo<PointerEventHandlers<PointerEvent>>(\n () => ({\n onPointerDown: (pos, evt) => {\n startRef.current = pos;\n setRect({ origin: { x: pos.x, y: pos.y }, size: { width: 0, height: 0 } });\n (evt.target as HTMLElement)?.setPointerCapture?.(evt.pointerId);\n },\n onPointerMove: (pos) => {\n if (!startRef.current) return;\n /* clamp current position to the page bounds */\n const curX = clamp(pos.x, 0, pageWidthPDF);\n const curY = clamp(pos.y, 0, pageHeightPDF);\n\n const { x: sx, y: sy } = startRef.current;\n const left = Math.min(sx, curX);\n const top = Math.min(sy, curY);\n const width = Math.abs(curX - sx);\n const height = Math.abs(curY - sy);\n\n setRect({ origin: { x: left, y: top }, size: { width, height } });\n },\n onPointerUp: (_, evt) => {\n if (rect && zoom) {\n const dragPx = Math.max(rect.size.width, rect.size.height) * scale;\n if (dragPx > 5) {\n // real drag → zoom to it\n zoom.zoomToArea(pageIndex, rect);\n } else {\n // tiny drag → simple zoom-in\n zoom.zoomIn();\n }\n }\n\n startRef.current = null;\n setRect(null);\n (evt.target as HTMLElement)?.releasePointerCapture?.(evt.pointerId);\n },\n onPointerCancel: (_, evt) => {\n startRef.current = null;\n setRect(null);\n (evt.target as HTMLElement)?.releasePointerCapture?.(evt.pointerId);\n },\n }),\n [pageWidthPDF, pageWidthPDF, zoom, scale, rect, pageIndex],\n );\n\n /* register with the interaction-manager */\n useEffect(() => {\n if (!register) return;\n return register(handlers);\n }, [register, handlers]);\n\n /* ------------------------------------------------------------------ */\n /* render */\n /* ------------------------------------------------------------------ */\n if (!rect) return null; // nothing to draw\n\n return (\n <div\n /* Each page wrapper is position:relative, so absolute is fine */\n style={{\n position: 'absolute',\n pointerEvents: 'none', // ignore hits – underlying page still gets events\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"],"mappings":"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","names":["useEffect","useCapability","useCapability","useEffect","useEffect","useRef","useState","jsx","useRef","useState","useEffect"]}
|
|
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, useMemo, useRef, useState } from '@framework';\nimport type { PointerEventHandlers } from '@embedpdf/plugin-interaction-manager';\nimport { usePointerHandlers } from '@embedpdf/plugin-interaction-manager/@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 /** Width of the page */\n pageWidth: number;\n /** Height of the page */\n pageHeight: 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\n/**\n * Draws a marquee rectangle while the user drags.\n * Hook it into the interaction-manager with modeId = 'marqueeZoom'.\n */\nexport const MarqueeZoom = ({\n pageIndex,\n scale,\n pageWidth,\n pageHeight,\n className,\n stroke = 'rgba(33,150,243,0.8)',\n fill = 'rgba(33,150,243,0.15)',\n}: MarqueeZoomProps) => {\n /* ------------------------------------------------------------------ */\n /* zoom capability */\n /* ------------------------------------------------------------------ */\n const { provides: zoom } = useZoomCapability();\n\n /* ------------------------------------------------------------------ */\n /* integration with interaction-manager */\n /* ------------------------------------------------------------------ */\n const { register } = usePointerHandlers({ modeId: 'marqueeZoom', pageIndex });\n\n /* ------------------------------------------------------------------ */\n /* helpers */\n /* ------------------------------------------------------------------ */\n const clamp = (v: number, min: number, max: number) => Math.max(min, Math.min(max, v));\n\n /* ------------------------------------------------------------------ */\n /* local state – start / current drag position */\n /* ------------------------------------------------------------------ */\n const startRef = useRef<{ x: number; y: number } | null>(null);\n const [rect, setRect] = useState<Rect | null>(null);\n\n /* page size in **PDF-space** (unscaled) ----------------------------- */\n const pageWidthPDF = pageWidth / scale;\n const pageHeightPDF = pageHeight / scale;\n\n /* ------------------------------------------------------------------ */\n /* pointer handlers */\n /* ------------------------------------------------------------------ */\n const handlers = useMemo<PointerEventHandlers<PointerEvent>>(\n () => ({\n onPointerDown: (pos, evt) => {\n startRef.current = pos;\n setRect({ origin: { x: pos.x, y: pos.y }, size: { width: 0, height: 0 } });\n (evt.target as HTMLElement)?.setPointerCapture?.(evt.pointerId);\n },\n onPointerMove: (pos) => {\n if (!startRef.current) return;\n /* clamp current position to the page bounds */\n const curX = clamp(pos.x, 0, pageWidthPDF);\n const curY = clamp(pos.y, 0, pageHeightPDF);\n\n const { x: sx, y: sy } = startRef.current;\n const left = Math.min(sx, curX);\n const top = Math.min(sy, curY);\n const width = Math.abs(curX - sx);\n const height = Math.abs(curY - sy);\n\n setRect({ origin: { x: left, y: top }, size: { width, height } });\n },\n onPointerUp: (_, evt) => {\n if (rect && zoom) {\n const dragPx = Math.max(rect.size.width, rect.size.height) * scale;\n if (dragPx > 5) {\n // real drag → zoom to it\n zoom.zoomToArea(pageIndex, rect);\n } else {\n // tiny drag → simple zoom-in\n zoom.zoomIn();\n }\n }\n\n startRef.current = null;\n setRect(null);\n (evt.target as HTMLElement)?.releasePointerCapture?.(evt.pointerId);\n },\n onPointerCancel: (_, evt) => {\n startRef.current = null;\n setRect(null);\n (evt.target as HTMLElement)?.releasePointerCapture?.(evt.pointerId);\n },\n }),\n [pageWidthPDF, pageWidthPDF, zoom, scale, rect, pageIndex],\n );\n\n /* register with the interaction-manager */\n useEffect(() => {\n if (!register) return;\n return register(handlers);\n }, [register, handlers]);\n\n /* ------------------------------------------------------------------ */\n /* render */\n /* ------------------------------------------------------------------ */\n if (!rect) return null; // nothing to draw\n\n return (\n <div\n /* Each page wrapper is position:relative, so absolute is fine */\n style={{\n position: 'absolute',\n pointerEvents: 'none', // ignore hits – underlying page still gets events\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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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from '@embedpdf/plugin-interaction-manager/preact';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from '@embedpdf/core/react';
|
package/dist/react/index.cjs
CHANGED
|
@@ -1,262 +1,2 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
|
|
3
|
-
var __defProp = Object.defineProperty;
|
|
4
|
-
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
-
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
-
var __getProtoOf = Object.getPrototypeOf;
|
|
7
|
-
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
-
var __export = (target, all) => {
|
|
9
|
-
for (var name in all)
|
|
10
|
-
__defProp(target, name, { get: all[name], enumerable: true });
|
|
11
|
-
};
|
|
12
|
-
var __copyProps = (to, from, except, desc) => {
|
|
13
|
-
if (from && typeof from === "object" || typeof from === "function") {
|
|
14
|
-
for (let key of __getOwnPropNames(from))
|
|
15
|
-
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
16
|
-
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
17
|
-
}
|
|
18
|
-
return to;
|
|
19
|
-
};
|
|
20
|
-
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
21
|
-
// If the importer is in node compatibility mode or this is not an ESM
|
|
22
|
-
// file that has been converted to a CommonJS file using a Babel-
|
|
23
|
-
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
24
|
-
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
25
|
-
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
26
|
-
mod
|
|
27
|
-
));
|
|
28
|
-
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
29
|
-
|
|
30
|
-
// src/react/index.ts
|
|
31
|
-
var react_exports = {};
|
|
32
|
-
__export(react_exports, {
|
|
33
|
-
MarqueeZoom: () => MarqueeZoom,
|
|
34
|
-
PinchWrapper: () => PinchWrapper,
|
|
35
|
-
usePinch: () => usePinch,
|
|
36
|
-
useZoom: () => useZoom,
|
|
37
|
-
useZoomCapability: () => useZoomCapability,
|
|
38
|
-
useZoomPlugin: () => useZoomPlugin
|
|
39
|
-
});
|
|
40
|
-
module.exports = __toCommonJS(react_exports);
|
|
41
|
-
|
|
42
|
-
// src/react/hooks/use-zoom.ts
|
|
43
|
-
var import_react = require("@embedpdf/core/react");
|
|
44
|
-
var import_plugin_zoom = require("@embedpdf/plugin-zoom");
|
|
45
|
-
var import_react2 = require("react");
|
|
46
|
-
var useZoomCapability = () => (0, import_react.useCapability)(import_plugin_zoom.ZoomPlugin.id);
|
|
47
|
-
var useZoomPlugin = () => (0, import_react.usePlugin)(import_plugin_zoom.ZoomPlugin.id);
|
|
48
|
-
var useZoom = () => {
|
|
49
|
-
const { provides } = useZoomCapability();
|
|
50
|
-
const [state, setState] = (0, import_react2.useState)(import_plugin_zoom.initialState);
|
|
51
|
-
(0, import_react2.useEffect)(() => {
|
|
52
|
-
return provides?.onStateChange((action) => {
|
|
53
|
-
setState(action);
|
|
54
|
-
});
|
|
55
|
-
}, [provides]);
|
|
56
|
-
return {
|
|
57
|
-
state,
|
|
58
|
-
provides
|
|
59
|
-
};
|
|
60
|
-
};
|
|
61
|
-
|
|
62
|
-
// src/react/hooks/use-pinch-zoom.ts
|
|
63
|
-
var import_react3 = require("react");
|
|
64
|
-
var import_react4 = require("@embedpdf/core/react");
|
|
65
|
-
function usePinch() {
|
|
66
|
-
const { provides: viewportProvides } = (0, import_react4.useCapability)("viewport");
|
|
67
|
-
const { provides: zoomProvides } = useZoomCapability();
|
|
68
|
-
const elementRef = (0, import_react3.useRef)(null);
|
|
69
|
-
(0, import_react3.useEffect)(() => {
|
|
70
|
-
const element = elementRef.current;
|
|
71
|
-
if (!element || !viewportProvides || !zoomProvides) {
|
|
72
|
-
return;
|
|
73
|
-
}
|
|
74
|
-
if (typeof window === "undefined") {
|
|
75
|
-
return;
|
|
76
|
-
}
|
|
77
|
-
let hammer;
|
|
78
|
-
let initialZoom = 0;
|
|
79
|
-
let lastCenter = { x: 0, y: 0 };
|
|
80
|
-
const getState = () => zoomProvides.getState();
|
|
81
|
-
const updateTransform = (scale) => {
|
|
82
|
-
element.style.transform = `scale(${scale})`;
|
|
83
|
-
};
|
|
84
|
-
const resetTransform = () => {
|
|
85
|
-
element.style.transform = "none";
|
|
86
|
-
element.style.transformOrigin = "0 0";
|
|
87
|
-
};
|
|
88
|
-
const pinchStart = (e) => {
|
|
89
|
-
initialZoom = getState().currentZoomLevel;
|
|
90
|
-
const contRect = viewportProvides.getBoundingRect();
|
|
91
|
-
lastCenter = {
|
|
92
|
-
x: e.center.x - contRect.origin.x,
|
|
93
|
-
y: e.center.y - contRect.origin.y
|
|
94
|
-
};
|
|
95
|
-
const innerRect = element.getBoundingClientRect();
|
|
96
|
-
element.style.transformOrigin = `${e.center.x - innerRect.left}px ${e.center.y - innerRect.top}px`;
|
|
97
|
-
if (e.srcEvent?.cancelable) {
|
|
98
|
-
e.srcEvent.preventDefault();
|
|
99
|
-
e.srcEvent.stopPropagation();
|
|
100
|
-
}
|
|
101
|
-
};
|
|
102
|
-
const pinchMove = (e) => {
|
|
103
|
-
updateTransform(e.scale);
|
|
104
|
-
if (e.srcEvent?.cancelable) {
|
|
105
|
-
e.srcEvent.preventDefault();
|
|
106
|
-
e.srcEvent.stopPropagation();
|
|
107
|
-
}
|
|
108
|
-
};
|
|
109
|
-
const pinchEnd = (e) => {
|
|
110
|
-
const delta = (e.scale - 1) * initialZoom;
|
|
111
|
-
zoomProvides.requestZoomBy(delta, { vx: lastCenter.x, vy: lastCenter.y });
|
|
112
|
-
resetTransform();
|
|
113
|
-
initialZoom = 0;
|
|
114
|
-
};
|
|
115
|
-
const setupHammer = async () => {
|
|
116
|
-
try {
|
|
117
|
-
const Hammer = (await import("hammerjs")).default;
|
|
118
|
-
const inputClass = (() => {
|
|
119
|
-
const MOBILE_REGEX = /mobile|tablet|ip(ad|hone|od)|android/i;
|
|
120
|
-
const SUPPORT_TOUCH = "ontouchstart" in window || navigator.maxTouchPoints > 0;
|
|
121
|
-
const SUPPORT_ONLY_TOUCH = SUPPORT_TOUCH && MOBILE_REGEX.test(navigator.userAgent);
|
|
122
|
-
if (SUPPORT_ONLY_TOUCH) return Hammer.TouchInput;
|
|
123
|
-
if (!SUPPORT_TOUCH) return Hammer.MouseInput;
|
|
124
|
-
return Hammer.TouchMouseInput;
|
|
125
|
-
})();
|
|
126
|
-
hammer = new Hammer(element, {
|
|
127
|
-
touchAction: "pan-x pan-y",
|
|
128
|
-
// allow scroll in every direction
|
|
129
|
-
inputClass
|
|
130
|
-
});
|
|
131
|
-
hammer.get("pinch").set({ enable: true, pointers: 2, threshold: 0.1 });
|
|
132
|
-
hammer.on("pinchstart", pinchStart);
|
|
133
|
-
hammer.on("pinchmove", pinchMove);
|
|
134
|
-
hammer.on("pinchend", pinchEnd);
|
|
135
|
-
} catch (error) {
|
|
136
|
-
console.warn("Failed to load HammerJS:", error);
|
|
137
|
-
}
|
|
138
|
-
};
|
|
139
|
-
setupHammer();
|
|
140
|
-
return () => {
|
|
141
|
-
hammer?.destroy();
|
|
142
|
-
resetTransform();
|
|
143
|
-
};
|
|
144
|
-
}, [viewportProvides, zoomProvides]);
|
|
145
|
-
return { elementRef };
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
// src/react/components/pinch-wrapper.tsx
|
|
149
|
-
var import_jsx_runtime = require("react/jsx-runtime");
|
|
150
|
-
function PinchWrapper({ children, style, ...props }) {
|
|
151
|
-
const { elementRef } = usePinch();
|
|
152
|
-
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
153
|
-
"div",
|
|
154
|
-
{
|
|
155
|
-
ref: elementRef,
|
|
156
|
-
...props,
|
|
157
|
-
style: {
|
|
158
|
-
...style,
|
|
159
|
-
display: "block",
|
|
160
|
-
width: "fit-content",
|
|
161
|
-
overflow: "visible",
|
|
162
|
-
boxSizing: "border-box",
|
|
163
|
-
margin: "0px auto"
|
|
164
|
-
},
|
|
165
|
-
children
|
|
166
|
-
}
|
|
167
|
-
);
|
|
168
|
-
}
|
|
169
|
-
|
|
170
|
-
// src/react/components/marquee-zoom.tsx
|
|
171
|
-
var import_react5 = require("react");
|
|
172
|
-
var import_react6 = require("@embedpdf/plugin-interaction-manager/react");
|
|
173
|
-
var import_jsx_runtime2 = require("react/jsx-runtime");
|
|
174
|
-
var MarqueeZoom = ({
|
|
175
|
-
pageIndex,
|
|
176
|
-
scale,
|
|
177
|
-
pageWidth,
|
|
178
|
-
pageHeight,
|
|
179
|
-
className,
|
|
180
|
-
stroke = "rgba(33,150,243,0.8)",
|
|
181
|
-
fill = "rgba(33,150,243,0.15)"
|
|
182
|
-
}) => {
|
|
183
|
-
const { provides: zoom } = useZoomCapability();
|
|
184
|
-
const { register } = (0, import_react6.usePointerHandlers)({ modeId: "marqueeZoom", pageIndex });
|
|
185
|
-
const clamp = (v, min, max) => Math.max(min, Math.min(max, v));
|
|
186
|
-
const startRef = (0, import_react5.useRef)(null);
|
|
187
|
-
const [rect, setRect] = (0, import_react5.useState)(null);
|
|
188
|
-
const pageWidthPDF = pageWidth / scale;
|
|
189
|
-
const pageHeightPDF = pageHeight / scale;
|
|
190
|
-
const handlers = (0, import_react5.useMemo)(
|
|
191
|
-
() => ({
|
|
192
|
-
onPointerDown: (pos, evt) => {
|
|
193
|
-
startRef.current = pos;
|
|
194
|
-
setRect({ origin: { x: pos.x, y: pos.y }, size: { width: 0, height: 0 } });
|
|
195
|
-
evt.target?.setPointerCapture?.(evt.pointerId);
|
|
196
|
-
},
|
|
197
|
-
onPointerMove: (pos) => {
|
|
198
|
-
if (!startRef.current) return;
|
|
199
|
-
const curX = clamp(pos.x, 0, pageWidthPDF);
|
|
200
|
-
const curY = clamp(pos.y, 0, pageHeightPDF);
|
|
201
|
-
const { x: sx, y: sy } = startRef.current;
|
|
202
|
-
const left = Math.min(sx, curX);
|
|
203
|
-
const top = Math.min(sy, curY);
|
|
204
|
-
const width = Math.abs(curX - sx);
|
|
205
|
-
const height = Math.abs(curY - sy);
|
|
206
|
-
setRect({ origin: { x: left, y: top }, size: { width, height } });
|
|
207
|
-
},
|
|
208
|
-
onPointerUp: (_, evt) => {
|
|
209
|
-
if (rect && zoom) {
|
|
210
|
-
const dragPx = Math.max(rect.size.width, rect.size.height) * scale;
|
|
211
|
-
if (dragPx > 5) {
|
|
212
|
-
zoom.zoomToArea(pageIndex, rect);
|
|
213
|
-
} else {
|
|
214
|
-
zoom.zoomIn();
|
|
215
|
-
}
|
|
216
|
-
}
|
|
217
|
-
startRef.current = null;
|
|
218
|
-
setRect(null);
|
|
219
|
-
evt.target?.releasePointerCapture?.(evt.pointerId);
|
|
220
|
-
},
|
|
221
|
-
onPointerCancel: (_, evt) => {
|
|
222
|
-
startRef.current = null;
|
|
223
|
-
setRect(null);
|
|
224
|
-
evt.target?.releasePointerCapture?.(evt.pointerId);
|
|
225
|
-
}
|
|
226
|
-
}),
|
|
227
|
-
[pageWidthPDF, pageWidthPDF, zoom, scale, rect, pageIndex]
|
|
228
|
-
);
|
|
229
|
-
(0, import_react5.useEffect)(() => {
|
|
230
|
-
if (!register) return;
|
|
231
|
-
return register(handlers);
|
|
232
|
-
}, [register, handlers]);
|
|
233
|
-
if (!rect) return null;
|
|
234
|
-
return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
235
|
-
"div",
|
|
236
|
-
{
|
|
237
|
-
style: {
|
|
238
|
-
position: "absolute",
|
|
239
|
-
pointerEvents: "none",
|
|
240
|
-
// ignore hits – underlying page still gets events
|
|
241
|
-
left: rect.origin.x * scale,
|
|
242
|
-
top: rect.origin.y * scale,
|
|
243
|
-
width: rect.size.width * scale,
|
|
244
|
-
height: rect.size.height * scale,
|
|
245
|
-
border: `1px solid ${stroke}`,
|
|
246
|
-
background: fill,
|
|
247
|
-
boxSizing: "border-box"
|
|
248
|
-
},
|
|
249
|
-
className
|
|
250
|
-
}
|
|
251
|
-
);
|
|
252
|
-
};
|
|
253
|
-
// Annotate the CommonJS export names for ESM import in node:
|
|
254
|
-
0 && (module.exports = {
|
|
255
|
-
MarqueeZoom,
|
|
256
|
-
PinchWrapper,
|
|
257
|
-
usePinch,
|
|
258
|
-
useZoom,
|
|
259
|
-
useZoomCapability,
|
|
260
|
-
useZoomPlugin
|
|
261
|
-
});
|
|
262
|
-
//# sourceMappingURL=index.cjs.map
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("@embedpdf/core/react"),t=require("@embedpdf/plugin-zoom"),n=require("react"),r=require("react/jsx-runtime"),o=require("@embedpdf/plugin-interaction-manager/react"),i=()=>e.useCapability(t.ZoomPlugin.id);function a(){const{provides:t}=e.useCapability("viewport"),{provides:r}=i(),o=n.useRef(null);return n.useEffect((()=>{const e=o.current;if(!e||!t||!r)return;if("undefined"==typeof window)return;let n,i=0,a={x:0,y:0};const s=()=>{e.style.transform="none",e.style.transformOrigin="0 0"},l=n=>{var o;i=r.getState().currentZoomLevel;const s=t.getBoundingRect();a={x:n.center.x-s.origin.x,y:n.center.y-s.origin.y};const l=e.getBoundingClientRect();e.style.transformOrigin=`${n.center.x-l.left}px ${n.center.y-l.top}px`,(null==(o=n.srcEvent)?void 0:o.cancelable)&&(n.srcEvent.preventDefault(),n.srcEvent.stopPropagation())},u=t=>{var n,r;r=t.scale,e.style.transform=`scale(${r})`,(null==(n=t.srcEvent)?void 0:n.cancelable)&&(t.srcEvent.preventDefault(),t.srcEvent.stopPropagation())},c=e=>{const t=(e.scale-1)*i;r.requestZoomBy(t,{vx:a.x,vy:a.y}),s(),i=0};return(async()=>{try{const t=(await Promise.resolve().then((()=>require("../hammer-Bs-QCG8V.cjs"))).then((e=>e.hammer))).default,r=(()=>{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:r}),n.get("pinch").set({enable:!0,pointers:2,threshold:.1}),n.on("pinchstart",l),n.on("pinchmove",u),n.on("pinchend",c)}catch(t){console.warn("Failed to load HammerJS:",t)}})(),()=>{null==n||n.destroy(),s()}}),[t,r]),{elementRef:o}}exports.MarqueeZoom=({pageIndex:e,scale:t,pageWidth:a,pageHeight:s,className:l,stroke:u="rgba(33,150,243,0.8)",fill:c="rgba(33,150,243,0.15)"})=>{const{provides:p}=i(),{register:d}=o.usePointerHandlers({modeId:"marqueeZoom",pageIndex:e}),g=(e,t,n)=>Math.max(t,Math.min(n,e)),h=n.useRef(null),[m,v]=n.useState(null),x=a/t,f=s/t,y=n.useMemo((()=>({onPointerDown:(e,t)=>{var n,r;h.current=e,v({origin:{x:e.x,y:e.y},size:{width:0,height:0}}),null==(r=null==(n=t.target)?void 0:n.setPointerCapture)||r.call(n,t.pointerId)},onPointerMove:e=>{if(!h.current)return;const t=g(e.x,0,x),n=g(e.y,0,f),{x:r,y:o}=h.current,i=Math.min(r,t),a=Math.min(o,n),s=Math.abs(t-r),l=Math.abs(n-o);v({origin:{x:i,y:a},size:{width:s,height:l}})},onPointerUp:(n,r)=>{var o,i;if(m&&p){Math.max(m.size.width,m.size.height)*t>5?p.zoomToArea(e,m):p.zoomIn()}h.current=null,v(null),null==(i=null==(o=r.target)?void 0:o.releasePointerCapture)||i.call(o,r.pointerId)},onPointerCancel:(e,t)=>{var n,r;h.current=null,v(null),null==(r=null==(n=t.target)?void 0:n.releasePointerCapture)||r.call(n,t.pointerId)}})),[x,x,p,t,m,e]);return n.useEffect((()=>{if(d)return d(y)}),[d,y]),m?r.jsx("div",{style:{position:"absolute",pointerEvents:"none",left:m.origin.x*t,top:m.origin.y*t,width:m.size.width*t,height:m.size.height*t,border:`1px solid ${u}`,background:c,boxSizing:"border-box"},className:l}):null},exports.PinchWrapper=function({children:e,style:t,...n}){const{elementRef:o}=a();return r.jsx("div",{ref:o,...n,style:{...t,display:"block",width:"fit-content",overflow:"visible",boxSizing:"border-box",margin:"0px auto"},children:e})},exports.usePinch=a,exports.useZoom=()=>{const{provides:e}=i(),[r,o]=n.useState(t.initialState);return n.useEffect((()=>null==e?void 0:e.onStateChange((e=>{o(e)}))),[e]),{state:r,provides:e}},exports.useZoomCapability=i,exports.useZoomPlugin=()=>e.usePlugin(t.ZoomPlugin.id);
|
|
2
|
+
//# sourceMappingURL=index.cjs.map
|
package/dist/react/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/react/index.ts","../../src/react/hooks/use-zoom.ts","../../src/react/hooks/use-pinch-zoom.ts","../../src/react/components/pinch-wrapper.tsx","../../src/react/components/marquee-zoom.tsx"],"sourcesContent":["export * from './hooks';\nexport * from './components';\n","import { useCapability, usePlugin } from '@embedpdf/core/react';\nimport { initialState, ZoomPlugin, ZoomState } from '@embedpdf/plugin-zoom';\nimport { useEffect, useState } from 'react';\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 'react';\nimport { useCapability } from '@embedpdf/core/react';\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 } from 'react';\n\nimport { usePinch } from '../hooks';\n\ntype PinchWrapperProps = Omit<React.HTMLAttributes<HTMLDivElement>, 'style'> & {\n children: ReactNode;\n style?: React.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, useMemo, useRef, useState } from 'react';\nimport type { PointerEventHandlers } from '@embedpdf/plugin-interaction-manager';\nimport { usePointerHandlers } from '@embedpdf/plugin-interaction-manager/react';\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 /** Width of the page */\n pageWidth: number;\n /** Height of the page */\n pageHeight: 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\n/**\n * Draws a marquee rectangle while the user drags.\n * Hook it into the interaction-manager with modeId = 'marqueeZoom'.\n */\nexport const MarqueeZoom = ({\n pageIndex,\n scale,\n pageWidth,\n pageHeight,\n className,\n stroke = 'rgba(33,150,243,0.8)',\n fill = 'rgba(33,150,243,0.15)',\n}: MarqueeZoomProps) => {\n /* ------------------------------------------------------------------ */\n /* zoom capability */\n /* ------------------------------------------------------------------ */\n const { provides: zoom } = useZoomCapability();\n\n /* ------------------------------------------------------------------ */\n /* integration with interaction-manager */\n /* ------------------------------------------------------------------ */\n const { register } = usePointerHandlers({ modeId: 'marqueeZoom', pageIndex });\n\n /* ------------------------------------------------------------------ */\n /* helpers */\n /* ------------------------------------------------------------------ */\n const clamp = (v: number, min: number, max: number) => Math.max(min, Math.min(max, v));\n\n /* ------------------------------------------------------------------ */\n /* local state – start / current drag position */\n /* ------------------------------------------------------------------ */\n const startRef = useRef<{ x: number; y: number } | null>(null);\n const [rect, setRect] = useState<Rect | null>(null);\n\n /* page size in **PDF-space** (unscaled) ----------------------------- */\n const pageWidthPDF = pageWidth / scale;\n const pageHeightPDF = pageHeight / scale;\n\n /* ------------------------------------------------------------------ */\n /* pointer handlers */\n /* ------------------------------------------------------------------ */\n const handlers = useMemo<PointerEventHandlers<PointerEvent>>(\n () => ({\n onPointerDown: (pos, evt) => {\n startRef.current = pos;\n setRect({ origin: { x: pos.x, y: pos.y }, size: { width: 0, height: 0 } });\n (evt.target as HTMLElement)?.setPointerCapture?.(evt.pointerId);\n },\n onPointerMove: (pos) => {\n if (!startRef.current) return;\n /* clamp current position to the page bounds */\n const curX = clamp(pos.x, 0, pageWidthPDF);\n const curY = clamp(pos.y, 0, pageHeightPDF);\n\n const { x: sx, y: sy } = startRef.current;\n const left = Math.min(sx, curX);\n const top = Math.min(sy, curY);\n const width = Math.abs(curX - sx);\n const height = Math.abs(curY - sy);\n\n setRect({ origin: { x: left, y: top }, size: { width, height } });\n },\n onPointerUp: (_, evt) => {\n if (rect && zoom) {\n const dragPx = Math.max(rect.size.width, rect.size.height) * scale;\n if (dragPx > 5) {\n // real drag → zoom to it\n zoom.zoomToArea(pageIndex, rect);\n } else {\n // tiny drag → simple zoom-in\n zoom.zoomIn();\n }\n }\n\n startRef.current = null;\n setRect(null);\n (evt.target as HTMLElement)?.releasePointerCapture?.(evt.pointerId);\n },\n onPointerCancel: (_, evt) => {\n startRef.current = null;\n setRect(null);\n (evt.target as HTMLElement)?.releasePointerCapture?.(evt.pointerId);\n },\n }),\n [pageWidthPDF, pageWidthPDF, zoom, scale, rect, pageIndex],\n );\n\n /* register with the interaction-manager */\n useEffect(() => {\n if (!register) return;\n return register(handlers);\n }, [register, handlers]);\n\n /* ------------------------------------------------------------------ */\n /* render */\n /* ------------------------------------------------------------------ */\n if (!rect) return null; // nothing to draw\n\n return (\n <div\n /* Each page wrapper is position:relative, so absolute is fine */\n style={{\n position: 'absolute',\n pointerEvents: 'none', // ignore hits – underlying page still gets events\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"],"mappings":"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","names":["import_react","import_react","import_react","import_jsx_runtime"]}
|
|
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, useMemo, useRef, useState } from '@framework';\nimport type { PointerEventHandlers } from '@embedpdf/plugin-interaction-manager';\nimport { usePointerHandlers } from '@embedpdf/plugin-interaction-manager/@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 /** Width of the page */\n pageWidth: number;\n /** Height of the page */\n pageHeight: 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\n/**\n * Draws a marquee rectangle while the user drags.\n * Hook it into the interaction-manager with modeId = 'marqueeZoom'.\n */\nexport const MarqueeZoom = ({\n pageIndex,\n scale,\n pageWidth,\n pageHeight,\n className,\n stroke = 'rgba(33,150,243,0.8)',\n fill = 'rgba(33,150,243,0.15)',\n}: MarqueeZoomProps) => {\n /* ------------------------------------------------------------------ */\n /* zoom capability */\n /* ------------------------------------------------------------------ */\n const { provides: zoom } = useZoomCapability();\n\n /* ------------------------------------------------------------------ */\n /* integration with interaction-manager */\n /* ------------------------------------------------------------------ */\n const { register } = usePointerHandlers({ modeId: 'marqueeZoom', pageIndex });\n\n /* ------------------------------------------------------------------ */\n /* helpers */\n /* ------------------------------------------------------------------ */\n const clamp = (v: number, min: number, max: number) => Math.max(min, Math.min(max, v));\n\n /* ------------------------------------------------------------------ */\n /* local state – start / current drag position */\n /* ------------------------------------------------------------------ */\n const startRef = useRef<{ x: number; y: number } | null>(null);\n const [rect, setRect] = useState<Rect | null>(null);\n\n /* page size in **PDF-space** (unscaled) ----------------------------- */\n const pageWidthPDF = pageWidth / scale;\n const pageHeightPDF = pageHeight / scale;\n\n /* ------------------------------------------------------------------ */\n /* pointer handlers */\n /* ------------------------------------------------------------------ */\n const handlers = useMemo<PointerEventHandlers<PointerEvent>>(\n () => ({\n onPointerDown: (pos, evt) => {\n startRef.current = pos;\n setRect({ origin: { x: pos.x, y: pos.y }, size: { width: 0, height: 0 } });\n (evt.target as HTMLElement)?.setPointerCapture?.(evt.pointerId);\n },\n onPointerMove: (pos) => {\n if (!startRef.current) return;\n /* clamp current position to the page bounds */\n const curX = clamp(pos.x, 0, pageWidthPDF);\n const curY = clamp(pos.y, 0, pageHeightPDF);\n\n const { x: sx, y: sy } = startRef.current;\n const left = Math.min(sx, curX);\n const top = Math.min(sy, curY);\n const width = Math.abs(curX - sx);\n const height = Math.abs(curY - sy);\n\n setRect({ origin: { x: left, y: top }, size: { width, height } });\n },\n onPointerUp: (_, evt) => {\n if (rect && zoom) {\n const dragPx = Math.max(rect.size.width, rect.size.height) * scale;\n if (dragPx > 5) {\n // real drag → zoom to it\n zoom.zoomToArea(pageIndex, rect);\n } else {\n // tiny drag → simple zoom-in\n zoom.zoomIn();\n }\n }\n\n startRef.current = null;\n setRect(null);\n (evt.target as HTMLElement)?.releasePointerCapture?.(evt.pointerId);\n },\n onPointerCancel: (_, evt) => {\n startRef.current = null;\n setRect(null);\n (evt.target as HTMLElement)?.releasePointerCapture?.(evt.pointerId);\n },\n }),\n [pageWidthPDF, pageWidthPDF, zoom, scale, rect, pageIndex],\n );\n\n /* register with the interaction-manager */\n useEffect(() => {\n if (!register) return;\n return register(handlers);\n }, [register, handlers]);\n\n /* ------------------------------------------------------------------ */\n /* render */\n /* ------------------------------------------------------------------ */\n if (!rect) return null; // nothing to draw\n\n return (\n <div\n /* Each page wrapper is position:relative, so absolute is fine */\n style={{\n position: 'absolute',\n pointerEvents: 'none', // ignore hits – underlying page still gets events\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","pageWidth","pageHeight","className","stroke","fill","zoom","register","usePointerHandlers","modeId","clamp","v","min","max","Math","startRef","rect","setRect","useState","pageWidthPDF","pageHeightPDF","handlers","useMemo","onPointerDown","pos","evt","size","width","height","_b","target","setPointerCapture","call","pointerId","onPointerMove","curX","curY","sx","sy","abs","onPointerUp","_","zoomToArea","zoomIn","releasePointerCapture","onPointerCancel","jsxRuntime","jsx","position","pointerEvents","border","background","boxSizing","children","props","ref","display","overflow","margin","state","setState","initialState","onStateChange","action","usePlugin"],"mappings":"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"}
|