@embedpdf/plugin-zoom 2.0.0-next.2 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/preact/adapter.d.ts +1 -1
- package/dist/preact/index.cjs +1 -1
- package/dist/preact/index.cjs.map +1 -1
- package/dist/preact/index.js +217 -71
- package/dist/preact/index.js.map +1 -1
- package/dist/preact/viewport.d.ts +1 -0
- package/dist/react/adapter.d.ts +1 -1
- package/dist/react/index.cjs +1 -1
- package/dist/react/index.cjs.map +1 -1
- package/dist/react/index.js +217 -71
- package/dist/react/index.js.map +1 -1
- package/dist/react/viewport.d.ts +1 -0
- package/dist/shared/components/index.d.ts +1 -1
- package/dist/shared/components/zoom-gesture-wrapper.d.ts +12 -0
- package/dist/shared/hooks/index.d.ts +1 -1
- package/dist/shared/hooks/use-pinch-zoom.d.ts +3 -1
- package/dist/shared/hooks/use-zoom-gesture.d.ts +5 -0
- package/dist/shared/utils/pinch-zoom-logic.d.ts +11 -2
- package/dist/shared/utils/zoom-gesture-logic.d.ts +18 -0
- package/dist/shared-preact/components/index.d.ts +1 -1
- package/dist/shared-preact/components/zoom-gesture-wrapper.d.ts +12 -0
- package/dist/shared-preact/hooks/index.d.ts +1 -1
- package/dist/shared-preact/hooks/use-pinch-zoom.d.ts +3 -1
- package/dist/shared-preact/hooks/use-zoom-gesture.d.ts +5 -0
- package/dist/shared-preact/utils/pinch-zoom-logic.d.ts +11 -2
- package/dist/shared-preact/utils/zoom-gesture-logic.d.ts +18 -0
- package/dist/shared-react/components/index.d.ts +1 -1
- package/dist/shared-react/components/zoom-gesture-wrapper.d.ts +12 -0
- package/dist/shared-react/hooks/index.d.ts +1 -1
- package/dist/shared-react/hooks/use-pinch-zoom.d.ts +3 -1
- package/dist/shared-react/hooks/use-zoom-gesture.d.ts +5 -0
- package/dist/shared-react/utils/pinch-zoom-logic.d.ts +11 -2
- package/dist/shared-react/utils/zoom-gesture-logic.d.ts +18 -0
- package/dist/shared-svelte/utils/zoom-gesture-logic.d.ts +18 -0
- package/dist/shared-vue/utils/zoom-gesture-logic.d.ts +18 -0
- package/dist/svelte/components/ZoomGestureWrapper.svelte.d.ts +14 -0
- package/dist/svelte/components/index.d.ts +1 -1
- package/dist/svelte/hooks/index.d.ts +1 -1
- package/dist/svelte/hooks/use-pinch-zoom.svelte.d.ts +11 -2
- package/dist/svelte/hooks/use-zoom-gesture.svelte.d.ts +16 -0
- package/dist/svelte/index.cjs +1 -1
- package/dist/svelte/index.cjs.map +1 -1
- package/dist/svelte/index.js +214 -71
- package/dist/svelte/index.js.map +1 -1
- package/dist/vue/components/index.d.ts +1 -1
- package/dist/vue/components/{pinch-wrapper.vue.d.ts → zoom-gesture-wrapper.vue.d.ts} +8 -1
- package/dist/vue/hooks/index.d.ts +1 -1
- package/dist/vue/hooks/use-zoom-gesture.d.ts +17 -0
- package/dist/vue/index.cjs +1 -1
- package/dist/vue/index.cjs.map +1 -1
- package/dist/vue/index.js +211 -72
- package/dist/vue/index.js.map +1 -1
- package/package.json +10 -12
- package/dist/hammer-DhVzwxwy.cjs +0 -7
- package/dist/hammer-DhVzwxwy.cjs.map +0 -1
- package/dist/hammer-e1aXHboh.js +0 -1810
- package/dist/hammer-e1aXHboh.js.map +0 -1
- package/dist/shared/components/pinch-wrapper.d.ts +0 -8
- package/dist/shared-preact/components/pinch-wrapper.d.ts +0 -8
- package/dist/shared-react/components/pinch-wrapper.d.ts +0 -8
- package/dist/shared-svelte/utils/pinch-zoom-logic.d.ts +0 -9
- package/dist/shared-vue/utils/pinch-zoom-logic.d.ts +0 -9
- package/dist/svelte/components/PinchWrapper.svelte.d.ts +0 -10
- package/dist/vue/hooks/use-pinch-zoom.d.ts +0 -8
package/dist/vue/index.cjs.map
CHANGED
|
@@ -1 +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, watch, readonly, computed, toValue, type MaybeRefOrGetter } from 'vue';\nimport { useCapability, usePlugin } from '@embedpdf/core/vue';\nimport { initialDocumentState, ZoomPlugin, ZoomDocumentState } from '@embedpdf/plugin-zoom';\n\nexport const useZoomCapability = () => useCapability<ZoomPlugin>(ZoomPlugin.id);\nexport const useZoomPlugin = () => usePlugin<ZoomPlugin>(ZoomPlugin.id);\n\n/**\n * Hook for zoom state for a specific document\n * @param documentId Document ID (can be ref, computed, getter, or plain value)\n */\nexport const useZoom = (documentId: MaybeRefOrGetter<string>) => {\n const { provides } = useZoomCapability();\n const state = ref<ZoomDocumentState>(initialDocumentState);\n\n watch(\n [provides, () => toValue(documentId)],\n ([providesValue, docId], _, onCleanup) => {\n if (!providesValue) {\n state.value = initialDocumentState;\n return;\n }\n\n const scope = providesValue.forDocument(docId);\n\n // Get initial state\n state.value = scope.getState();\n\n // Subscribe to state changes\n const unsubscribe = scope.onStateChange((newState) => {\n state.value = newState;\n });\n\n onCleanup(unsubscribe);\n },\n { immediate: true },\n );\n\n // Return a computed ref for the scoped capability\n const scopedProvides = computed(() => {\n const docId = toValue(documentId);\n return provides.value?.forDocument(docId) ?? null;\n });\n\n return {\n state: readonly(state),\n provides: scopedProvides,\n };\n};\n","import type { ViewportCapability } from '@embedpdf/plugin-viewport';\nimport type { ZoomCapability } from '@embedpdf/plugin-zoom';\n\nexport interface PinchZoomDeps {\n element: HTMLDivElement;\n documentId: string;\n viewportProvides: ViewportCapability;\n zoomProvides: ZoomCapability;\n}\n\nexport function setupPinchZoom({\n element,\n documentId,\n viewportProvides,\n zoomProvides,\n}: PinchZoomDeps) {\n if (typeof window === 'undefined') {\n return () => {};\n }\n\n let hammer: any | undefined;\n let initialZoom = 0;\n let lastCenter = { x: 0, y: 0 };\n\n const viewportScope = viewportProvides.forDocument(documentId);\n const zoomScope = zoomProvides.forDocument(documentId);\n\n const getState = () => zoomScope.getState();\n\n const updateTransform = (scale: number) => {\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 = viewportScope.getBoundingRect();\n\n lastCenter = {\n x: e.center.x - contRect.origin.x,\n y: e.center.y - contRect.origin.y,\n };\n\n const innerRect = element.getBoundingClientRect();\n element.style.transformOrigin = `${e.center.x - innerRect.left}px ${e.center.y - innerRect.top}px`;\n\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);\n if (e.srcEvent?.cancelable) {\n e.srcEvent.preventDefault();\n e.srcEvent.stopPropagation();\n }\n };\n\n const pinchEnd = (e: HammerInput) => {\n const delta = (e.scale - 1) * initialZoom;\n zoomScope.requestZoomBy(delta, { vx: lastCenter.x, vy: lastCenter.y });\n\n resetTransform();\n initialZoom = 0;\n };\n\n const setupHammer = async () => {\n try {\n const Hammer = (await import('hammerjs')).default;\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',\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}\n","import { ref, watch, toValue, type MaybeRefOrGetter } 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\n/**\n * Hook for setting up pinch-to-zoom functionality on an element\n * @param documentId Document ID (can be ref, computed, getter, or plain value)\n */\nexport function usePinch(documentId: MaybeRefOrGetter<string>) {\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 watch(\n [elementRef, viewportProvides, zoomProvides, () => toValue(documentId)],\n ([element, viewport, zoom, docId]) => {\n // Clean up previous setup\n if (cleanup) {\n cleanup();\n cleanup = undefined;\n }\n\n // Setup new pinch zoom if all dependencies are available\n if (!element || !viewport || !zoom) {\n return;\n }\n\n cleanup = setupPinchZoom({\n element,\n documentId: docId,\n viewportProvides: viewport,\n zoomProvides: zoom,\n });\n },\n { immediate: true },\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 * actualScale}px`,\n top: `${rect.origin.y * actualScale}px`,\n width: `${rect.size.width * actualScale}px`,\n height: `${rect.size.height * actualScale}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, computed, watch } from 'vue';\nimport type { Rect } from '@embedpdf/models';\nimport { useDocumentState } from '@embedpdf/core/vue';\nimport { useZoomCapability } from '../hooks';\n\ninterface MarqueeZoomProps {\n /** The ID of the document */\n documentId: string;\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 documentState = useDocumentState(() => props.documentId);\nconst rect = ref<Rect | null>(null);\n\nconst actualScale = computed(() => {\n if (props.scale !== undefined) return props.scale;\n return documentState.value?.scale ?? 1;\n});\n\nwatch(\n [zoomPlugin, () => props.documentId, () => props.pageIndex, actualScale],\n ([plugin, docId, pageIdx, scale], _, onCleanup) => {\n if (!plugin) {\n rect.value = null;\n return;\n }\n\n const unregister = plugin.registerMarqueeOnPage({\n documentId: docId,\n pageIndex: pageIdx,\n scale,\n callback: {\n onPreview: (newRect) => {\n rect.value = newRect;\n },\n },\n });\n\n onCleanup(() => {\n unregister?.();\n });\n },\n { immediate: true },\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\ninterface Props {\n documentId: string;\n}\n\nconst props = defineProps<Props>();\n\nconst { elementRef } = usePinch(props.documentId);\n</script>\n"],"names":["useZoomCapability","useCapability","ZoomPlugin","id","setupPinchZoom","element","documentId","viewportProvides","zoomProvides","window","hammer","initialZoom","lastCenter","x","y","viewportScope","forDocument","zoomScope","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","watch","toValue","viewport","zoom","docId","immediate","props","__props","zoomPlugin","documentState","useDocumentState","rect","actualScale","computed","value","pageIndex","plugin","pageIdx","_","onCleanup","unregister","registerMarqueeOnPage","callback","onPreview","newRect","_createElementBlock","_normalizeStyle","width","size","height","stroke","fill","class","className","_openBlock","_mergeProps","$attrs","_renderSlot","_ctx","$slots","state","initialDocumentState","providesValue","scope","onStateChange","newState","scopedProvides","readonly","usePlugin"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.cjs","sources":["../../src/vue/hooks/use-zoom.ts","../../src/shared/utils/zoom-gesture-logic.ts","../../src/vue/hooks/use-zoom-gesture.ts","../../src/vue/components/marquee-zoom.vue","../../src/vue/components/zoom-gesture-wrapper.vue"],"sourcesContent":["import { ref, watch, readonly, computed, toValue, type MaybeRefOrGetter } from 'vue';\nimport { useCapability, usePlugin } from '@embedpdf/core/vue';\nimport { initialDocumentState, ZoomPlugin, ZoomDocumentState } from '@embedpdf/plugin-zoom';\n\nexport const useZoomCapability = () => useCapability<ZoomPlugin>(ZoomPlugin.id);\nexport const useZoomPlugin = () => usePlugin<ZoomPlugin>(ZoomPlugin.id);\n\n/**\n * Hook for zoom state for a specific document\n * @param documentId Document ID (can be ref, computed, getter, or plain value)\n */\nexport const useZoom = (documentId: MaybeRefOrGetter<string>) => {\n const { provides } = useZoomCapability();\n const state = ref<ZoomDocumentState>(initialDocumentState);\n\n watch(\n [provides, () => toValue(documentId)],\n ([providesValue, docId], _, onCleanup) => {\n if (!providesValue) {\n state.value = initialDocumentState;\n return;\n }\n\n const scope = providesValue.forDocument(docId);\n\n // Get initial state\n state.value = scope.getState();\n\n // Subscribe to state changes\n const unsubscribe = scope.onStateChange((newState) => {\n state.value = newState;\n });\n\n onCleanup(unsubscribe);\n },\n { immediate: true },\n );\n\n // Return a computed ref for the scoped capability\n const scopedProvides = computed(() => {\n const docId = toValue(documentId);\n return provides.value?.forDocument(docId) ?? null;\n });\n\n return {\n state: readonly(state),\n provides: scopedProvides,\n };\n};\n","import type { ZoomCapability } from '@embedpdf/plugin-zoom';\n\nexport interface ZoomGestureOptions {\n /** Enable pinch-to-zoom gesture (default: true) */\n enablePinch?: boolean;\n /** Enable wheel zoom with ctrl/cmd key (default: true) */\n enableWheel?: boolean;\n}\n\nexport interface ZoomGestureDeps {\n element: HTMLDivElement;\n /** Viewport container element for attaching events */\n container: HTMLElement;\n documentId: string;\n zoomProvides: ZoomCapability;\n /** Viewport gap in pixels (default: 0) */\n viewportGap?: number;\n options?: ZoomGestureOptions;\n}\n\nfunction getTouchDistance(touches: TouchList): number {\n const [t1, t2] = [touches[0], touches[1]];\n const dx = t2.clientX - t1.clientX;\n const dy = t2.clientY - t1.clientY;\n return Math.hypot(dx, dy);\n}\n\nfunction getTouchCenter(touches: TouchList): { x: number; y: number } {\n const [t1, t2] = [touches[0], touches[1]];\n return {\n x: (t1.clientX + t2.clientX) / 2,\n y: (t1.clientY + t2.clientY) / 2,\n };\n}\n\nexport function setupZoomGestures({\n element,\n container,\n documentId,\n zoomProvides,\n viewportGap = 0,\n options = {},\n}: ZoomGestureDeps) {\n const { enablePinch = true, enableWheel = true } = options;\n if (typeof window === 'undefined') {\n return () => {};\n }\n\n const zoomScope = zoomProvides.forDocument(documentId);\n const getState = () => zoomScope.getState();\n\n // Shared state\n let initialZoom = 0;\n let currentScale = 1;\n let isPinching = false;\n let initialDistance = 0;\n\n // Wheel state\n let wheelZoomTimeout: ReturnType<typeof setTimeout> | null = null;\n let accumulatedWheelScale = 1;\n\n // Gesture state\n let initialElementWidth = 0;\n let initialElementHeight = 0;\n let initialElementLeft = 0;\n let initialElementTop = 0;\n\n // Container Dimensions (Bounding Box)\n let containerRectWidth = 0;\n let containerRectHeight = 0;\n\n // Layout Dimensions (Client Box from Metrics)\n let layoutWidth = 0;\n let layoutCenterX = 0;\n\n let pointerLocalY = 0;\n let pointerContainerX = 0;\n let pointerContainerY = 0;\n\n let currentGap = 0;\n let pivotLocalX = 0;\n\n const clamp = (val: number, min: number, max: number) => Math.min(Math.max(val, min), max);\n\n // --- Margin calculation ---\n const updateMargin = () => {\n const availableWidth = container.clientWidth - 2 * viewportGap;\n const elementWidth = element.offsetWidth;\n\n const newMargin = elementWidth < availableWidth ? (availableWidth - elementWidth) / 2 : 0;\n element.style.marginLeft = `${newMargin}px`;\n };\n\n const calculateTransform = (scale: number) => {\n const finalWidth = initialElementWidth * scale;\n const finalHeight = initialElementHeight * scale;\n\n let ty = pointerLocalY * (1 - scale);\n\n const targetX = layoutCenterX - finalWidth / 2;\n const txCenter = targetX - initialElementLeft;\n const txMouse = pointerContainerX - pivotLocalX * scale - initialElementLeft;\n\n const overflow = Math.max(0, finalWidth - layoutWidth);\n const blendRange = layoutWidth * 0.3;\n const blend = Math.min(1, overflow / blendRange);\n\n let tx = txCenter + (txMouse - txCenter) * blend;\n\n const safeHeight = containerRectHeight - currentGap * 2;\n if (finalHeight > safeHeight) {\n const currentTop = initialElementTop + ty;\n const maxTop = currentGap;\n const minTop = containerRectHeight - currentGap - finalHeight;\n const constrainedTop = clamp(currentTop, minTop, maxTop);\n ty = constrainedTop - initialElementTop;\n }\n\n const safeWidth = containerRectWidth - currentGap * 2;\n if (finalWidth > safeWidth) {\n const currentLeft = initialElementLeft + tx;\n const maxLeft = currentGap;\n const minLeft = containerRectWidth - currentGap - finalWidth;\n const constrainedLeft = clamp(currentLeft, minLeft, maxLeft);\n tx = constrainedLeft - initialElementLeft;\n }\n\n return { tx, ty, blend, finalWidth };\n };\n\n const updateTransform = (scale: number) => {\n currentScale = scale;\n const { tx, ty } = calculateTransform(scale);\n element.style.transformOrigin = '0 0';\n element.style.transform = `translate(${tx}px, ${ty}px) scale(${scale})`;\n };\n\n const resetTransform = () => {\n element.style.transform = 'none';\n element.style.transformOrigin = '0 0';\n currentScale = 1;\n };\n\n const commitZoom = () => {\n const { tx, finalWidth } = calculateTransform(currentScale);\n const delta = (currentScale - 1) * initialZoom;\n\n let anchorX: number;\n let anchorY: number = pointerContainerY;\n\n if (finalWidth <= layoutWidth) {\n anchorX = layoutCenterX;\n } else {\n const scaleDiff = 1 - currentScale;\n anchorX =\n Math.abs(scaleDiff) > 0.001 ? initialElementLeft + tx / scaleDiff : pointerContainerX;\n }\n\n zoomScope.requestZoomBy(delta, { vx: anchorX, vy: anchorY });\n resetTransform();\n initialZoom = 0;\n };\n\n const initializeGestureState = (clientX: number, clientY: number) => {\n const containerRect = container.getBoundingClientRect();\n const innerRect = element.getBoundingClientRect();\n\n currentGap = viewportGap;\n initialElementWidth = innerRect.width;\n initialElementHeight = innerRect.height;\n initialElementLeft = innerRect.left - containerRect.left;\n initialElementTop = innerRect.top - containerRect.top;\n\n containerRectWidth = containerRect.width;\n containerRectHeight = containerRect.height;\n\n // Layout dimensions from container's client area\n layoutWidth = container.clientWidth;\n layoutCenterX = container.clientLeft + layoutWidth / 2;\n\n const rawPointerLocalX = clientX - innerRect.left;\n pointerLocalY = clientY - innerRect.top;\n pointerContainerX = clientX - containerRect.left;\n pointerContainerY = clientY - containerRect.top;\n\n if (initialElementWidth < layoutWidth) {\n pivotLocalX = (pointerContainerX * initialElementWidth) / layoutWidth;\n } else {\n pivotLocalX = rawPointerLocalX;\n }\n };\n\n // --- Handlers ---\n const handleTouchStart = (e: TouchEvent) => {\n if (e.touches.length !== 2) return;\n isPinching = true;\n initialZoom = getState().currentZoomLevel;\n initialDistance = getTouchDistance(e.touches);\n const center = getTouchCenter(e.touches);\n initializeGestureState(center.x, center.y);\n e.preventDefault();\n };\n\n const handleTouchMove = (e: TouchEvent) => {\n if (!isPinching || e.touches.length !== 2) return;\n const currentDistance = getTouchDistance(e.touches);\n const scale = currentDistance / initialDistance;\n updateTransform(scale);\n e.preventDefault();\n };\n\n const handleTouchEnd = (e: TouchEvent) => {\n if (!isPinching) return;\n if (e.touches.length >= 2) return;\n isPinching = false;\n commitZoom();\n };\n\n const handleWheel = (e: WheelEvent) => {\n if (!e.ctrlKey && !e.metaKey) return;\n e.preventDefault();\n\n if (wheelZoomTimeout === null) {\n initialZoom = getState().currentZoomLevel;\n accumulatedWheelScale = 1;\n initializeGestureState(e.clientX, e.clientY);\n } else {\n clearTimeout(wheelZoomTimeout);\n }\n\n const zoomFactor = 1 - e.deltaY * 0.01;\n accumulatedWheelScale *= zoomFactor;\n accumulatedWheelScale = Math.max(0.1, Math.min(10, accumulatedWheelScale));\n updateTransform(accumulatedWheelScale);\n\n wheelZoomTimeout = setTimeout(() => {\n wheelZoomTimeout = null;\n commitZoom();\n accumulatedWheelScale = 1;\n }, 150);\n };\n\n // Subscribe to zoom changes to update margin\n const unsubZoom = zoomScope.onStateChange(() => updateMargin());\n\n // Use ResizeObserver to update margin when element or container size changes\n const resizeObserver = new ResizeObserver(() => updateMargin());\n resizeObserver.observe(element);\n resizeObserver.observe(container);\n\n // Initial margin calculation\n updateMargin();\n\n // Attach events to the viewport container for better UX\n // (gestures work anywhere in viewport, not just on the PDF)\n if (enablePinch) {\n container.addEventListener('touchstart', handleTouchStart, { passive: false });\n container.addEventListener('touchmove', handleTouchMove, { passive: false });\n container.addEventListener('touchend', handleTouchEnd);\n container.addEventListener('touchcancel', handleTouchEnd);\n }\n if (enableWheel) {\n container.addEventListener('wheel', handleWheel, { passive: false });\n }\n\n return () => {\n if (enablePinch) {\n container.removeEventListener('touchstart', handleTouchStart);\n container.removeEventListener('touchmove', handleTouchMove);\n container.removeEventListener('touchend', handleTouchEnd);\n container.removeEventListener('touchcancel', handleTouchEnd);\n }\n if (enableWheel) {\n container.removeEventListener('wheel', handleWheel);\n }\n if (wheelZoomTimeout) {\n clearTimeout(wheelZoomTimeout);\n }\n unsubZoom();\n resizeObserver.disconnect();\n resetTransform();\n element.style.marginLeft = '';\n };\n}\n","import { ref, watch, toValue, inject, type MaybeRefOrGetter, type Ref } from 'vue';\nimport { useCapability } from '@embedpdf/core/vue';\nimport type { ViewportPlugin, ViewportCapability } from '@embedpdf/plugin-viewport';\n\nimport { setupZoomGestures, type ZoomGestureOptions } from '../../shared/utils/zoom-gesture-logic';\nimport { useZoomCapability } from './use-zoom';\nimport type { ZoomCapability } from '../../lib/types';\n\nexport type { ZoomGestureOptions };\n\nexport interface UseZoomGestureOptions {\n /** Enable pinch-to-zoom gesture (default: true) */\n enablePinch?: MaybeRefOrGetter<boolean>;\n /** Enable wheel zoom with ctrl/cmd key (default: true) */\n enableWheel?: MaybeRefOrGetter<boolean>;\n}\n\n/**\n * Hook for setting up zoom gesture functionality (pinch and wheel zoom) on an element\n * @param documentId Document ID (can be ref, computed, getter, or plain value)\n * @param options Optional configuration for enabling/disabling gestures\n */\nexport function useZoomGesture(\n documentId: MaybeRefOrGetter<string>,\n options: UseZoomGestureOptions = {},\n) {\n const { provides: viewportProvides } = useCapability<ViewportPlugin>('viewport');\n const { provides: zoomProvides } = useZoomCapability();\n const viewportElementRef = inject<Ref<HTMLDivElement | null> | undefined>('viewport-element');\n const elementRef = ref<HTMLDivElement | null>(null);\n\n let cleanup: (() => void) | undefined;\n\n watch(\n [\n elementRef,\n viewportProvides,\n zoomProvides,\n () => toValue(documentId),\n () => toValue(options.enablePinch ?? true),\n () => toValue(options.enableWheel ?? true),\n ],\n ([element, viewport, zoom, docId, enablePinch, enableWheel]: [\n HTMLDivElement | null,\n ViewportCapability | null,\n ZoomCapability | null,\n string,\n boolean,\n boolean,\n ]) => {\n // Clean up previous setup\n if (cleanup) {\n cleanup();\n cleanup = undefined;\n }\n\n const container = viewportElementRef?.value;\n\n // Setup new zoom gestures if all dependencies are available\n if (!element || !container || !zoom) {\n return;\n }\n\n cleanup = setupZoomGestures({\n element,\n container,\n documentId: docId,\n zoomProvides: zoom,\n viewportGap: viewport?.getViewportGap() || 0,\n options: { enablePinch, enableWheel },\n });\n },\n { immediate: true },\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 * actualScale}px`,\n top: `${rect.origin.y * actualScale}px`,\n width: `${rect.size.width * actualScale}px`,\n height: `${rect.size.height * actualScale}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, computed, watch } from 'vue';\nimport type { Rect } from '@embedpdf/models';\nimport { useDocumentState } from '@embedpdf/core/vue';\nimport { useZoomCapability } from '../hooks';\n\ninterface MarqueeZoomProps {\n /** The ID of the document */\n documentId: string;\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 documentState = useDocumentState(() => props.documentId);\nconst rect = ref<Rect | null>(null);\n\nconst actualScale = computed(() => {\n if (props.scale !== undefined) return props.scale;\n return documentState.value?.scale ?? 1;\n});\n\nwatch(\n [zoomPlugin, () => props.documentId, () => props.pageIndex, actualScale],\n ([plugin, docId, pageIdx, scale], _, onCleanup) => {\n if (!plugin) {\n rect.value = null;\n return;\n }\n\n const unregister = plugin.registerMarqueeOnPage({\n documentId: docId,\n pageIndex: pageIdx,\n scale,\n callback: {\n onPreview: (newRect) => {\n rect.value = newRect;\n },\n },\n });\n\n onCleanup(() => {\n unregister?.();\n });\n },\n { immediate: true },\n);\n</script>\n","<template>\n <div\n ref=\"elementRef\"\n :style=\"{\n display: 'inline-block',\n overflow: 'visible',\n boxSizing: 'border-box',\n }\"\n v-bind=\"$attrs\"\n >\n <slot />\n </div>\n</template>\n\n<script setup lang=\"ts\">\nimport { toRef } from 'vue';\nimport { useZoomGesture } from '../hooks/use-zoom-gesture';\n\ninterface Props {\n documentId: string;\n /** Enable pinch-to-zoom gesture (default: true) */\n enablePinch?: boolean;\n /** Enable wheel zoom with ctrl/cmd key (default: true) */\n enableWheel?: boolean;\n}\n\nconst props = withDefaults(defineProps<Props>(), {\n enablePinch: true,\n enableWheel: true,\n});\n\nconst { elementRef } = useZoomGesture(() => props.documentId, {\n enablePinch: toRef(() => props.enablePinch),\n enableWheel: toRef(() => props.enableWheel),\n});\n</script>\n"],"names":["useZoomCapability","useCapability","ZoomPlugin","id","getTouchDistance","touches","t1","t2","dx","clientX","dy","clientY","Math","hypot","useZoomGesture","documentId","options","provides","viewportProvides","zoomProvides","viewportElementRef","inject","elementRef","ref","cleanup","watch","toValue","enablePinch","enableWheel","element","viewport","zoom","docId","container","value","viewportGap","window","zoomScope","forDocument","getState","initialZoom","currentScale","isPinching","initialDistance","wheelZoomTimeout","accumulatedWheelScale","initialElementWidth","initialElementHeight","initialElementLeft","initialElementTop","containerRectWidth","containerRectHeight","layoutWidth","layoutCenterX","pointerLocalY","pointerContainerX","pointerContainerY","currentGap","pivotLocalX","clamp","val","min","max","updateMargin","availableWidth","clientWidth","elementWidth","offsetWidth","newMargin","style","marginLeft","calculateTransform","scale","finalWidth","finalHeight","ty","txCenter","txMouse","overflow","blendRange","blend","tx","updateTransform","transformOrigin","transform","resetTransform","commitZoom","delta","anchorX","anchorY","scaleDiff","abs","requestZoomBy","vx","vy","initializeGestureState","containerRect","getBoundingClientRect","innerRect","width","height","left","top","clientLeft","rawPointerLocalX","handleTouchStart","e","length","currentZoomLevel","center","x","y","getTouchCenter","preventDefault","handleTouchMove","currentDistance","handleTouchEnd","handleWheel","ctrlKey","metaKey","clearTimeout","zoomFactor","deltaY","setTimeout","unsubZoom","onStateChange","resizeObserver","ResizeObserver","observe","addEventListener","passive","removeEventListener","disconnect","setupZoomGestures","getViewportGap","immediate","props","__props","zoomPlugin","documentState","useDocumentState","rect","actualScale","computed","_a","pageIndex","plugin","pageIdx","_","onCleanup","unregister","registerMarqueeOnPage","callback","onPreview","newRect","_createElementBlock","_normalizeStyle","origin","size","stroke","fill","class","className","toRef","_openBlock","_mergeProps","$attrs","_renderSlot","_ctx","$slots","state","initialDocumentState","providesValue","scope","newState","scopedProvides","readonly","usePlugin"],"mappings":"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"}
|
package/dist/vue/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { ref, watch, toValue, computed, readonly, defineComponent, createElementBlock, createCommentVNode, openBlock, normalizeClass, normalizeStyle, mergeProps, renderSlot } from "vue";
|
|
1
|
+
import { ref, watch, toValue, computed, readonly, inject, defineComponent, createElementBlock, createCommentVNode, openBlock, normalizeClass, normalizeStyle, toRef, mergeProps, renderSlot } from "vue";
|
|
2
2
|
import { useCapability, usePlugin, useDocumentState } from "@embedpdf/core/vue";
|
|
3
3
|
import { ZoomPlugin, initialDocumentState } from "@embedpdf/plugin-zoom";
|
|
4
4
|
export * from "@embedpdf/plugin-zoom";
|
|
@@ -33,107 +33,243 @@ const useZoom = (documentId) => {
|
|
|
33
33
|
provides: scopedProvides
|
|
34
34
|
};
|
|
35
35
|
};
|
|
36
|
-
function
|
|
36
|
+
function getTouchDistance(touches) {
|
|
37
|
+
const [t1, t2] = [touches[0], touches[1]];
|
|
38
|
+
const dx = t2.clientX - t1.clientX;
|
|
39
|
+
const dy = t2.clientY - t1.clientY;
|
|
40
|
+
return Math.hypot(dx, dy);
|
|
41
|
+
}
|
|
42
|
+
function getTouchCenter(touches) {
|
|
43
|
+
const [t1, t2] = [touches[0], touches[1]];
|
|
44
|
+
return {
|
|
45
|
+
x: (t1.clientX + t2.clientX) / 2,
|
|
46
|
+
y: (t1.clientY + t2.clientY) / 2
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
function setupZoomGestures({
|
|
37
50
|
element,
|
|
51
|
+
container,
|
|
38
52
|
documentId,
|
|
39
|
-
|
|
40
|
-
|
|
53
|
+
zoomProvides,
|
|
54
|
+
viewportGap = 0,
|
|
55
|
+
options = {}
|
|
41
56
|
}) {
|
|
57
|
+
const { enablePinch = true, enableWheel = true } = options;
|
|
42
58
|
if (typeof window === "undefined") {
|
|
43
59
|
return () => {
|
|
44
60
|
};
|
|
45
61
|
}
|
|
46
|
-
let hammer;
|
|
47
|
-
let initialZoom = 0;
|
|
48
|
-
let lastCenter = { x: 0, y: 0 };
|
|
49
|
-
const viewportScope = viewportProvides.forDocument(documentId);
|
|
50
62
|
const zoomScope = zoomProvides.forDocument(documentId);
|
|
51
63
|
const getState = () => zoomScope.getState();
|
|
64
|
+
let initialZoom = 0;
|
|
65
|
+
let currentScale = 1;
|
|
66
|
+
let isPinching = false;
|
|
67
|
+
let initialDistance = 0;
|
|
68
|
+
let wheelZoomTimeout = null;
|
|
69
|
+
let accumulatedWheelScale = 1;
|
|
70
|
+
let initialElementWidth = 0;
|
|
71
|
+
let initialElementHeight = 0;
|
|
72
|
+
let initialElementLeft = 0;
|
|
73
|
+
let initialElementTop = 0;
|
|
74
|
+
let containerRectWidth = 0;
|
|
75
|
+
let containerRectHeight = 0;
|
|
76
|
+
let layoutWidth = 0;
|
|
77
|
+
let layoutCenterX = 0;
|
|
78
|
+
let pointerLocalY = 0;
|
|
79
|
+
let pointerContainerX = 0;
|
|
80
|
+
let pointerContainerY = 0;
|
|
81
|
+
let currentGap = 0;
|
|
82
|
+
let pivotLocalX = 0;
|
|
83
|
+
const clamp = (val, min, max) => Math.min(Math.max(val, min), max);
|
|
84
|
+
const updateMargin = () => {
|
|
85
|
+
const availableWidth = container.clientWidth - 2 * viewportGap;
|
|
86
|
+
const elementWidth = element.offsetWidth;
|
|
87
|
+
const newMargin = elementWidth < availableWidth ? (availableWidth - elementWidth) / 2 : 0;
|
|
88
|
+
element.style.marginLeft = `${newMargin}px`;
|
|
89
|
+
};
|
|
90
|
+
const calculateTransform = (scale) => {
|
|
91
|
+
const finalWidth = initialElementWidth * scale;
|
|
92
|
+
const finalHeight = initialElementHeight * scale;
|
|
93
|
+
let ty = pointerLocalY * (1 - scale);
|
|
94
|
+
const targetX = layoutCenterX - finalWidth / 2;
|
|
95
|
+
const txCenter = targetX - initialElementLeft;
|
|
96
|
+
const txMouse = pointerContainerX - pivotLocalX * scale - initialElementLeft;
|
|
97
|
+
const overflow = Math.max(0, finalWidth - layoutWidth);
|
|
98
|
+
const blendRange = layoutWidth * 0.3;
|
|
99
|
+
const blend = Math.min(1, overflow / blendRange);
|
|
100
|
+
let tx = txCenter + (txMouse - txCenter) * blend;
|
|
101
|
+
const safeHeight = containerRectHeight - currentGap * 2;
|
|
102
|
+
if (finalHeight > safeHeight) {
|
|
103
|
+
const currentTop = initialElementTop + ty;
|
|
104
|
+
const maxTop = currentGap;
|
|
105
|
+
const minTop = containerRectHeight - currentGap - finalHeight;
|
|
106
|
+
const constrainedTop = clamp(currentTop, minTop, maxTop);
|
|
107
|
+
ty = constrainedTop - initialElementTop;
|
|
108
|
+
}
|
|
109
|
+
const safeWidth = containerRectWidth - currentGap * 2;
|
|
110
|
+
if (finalWidth > safeWidth) {
|
|
111
|
+
const currentLeft = initialElementLeft + tx;
|
|
112
|
+
const maxLeft = currentGap;
|
|
113
|
+
const minLeft = containerRectWidth - currentGap - finalWidth;
|
|
114
|
+
const constrainedLeft = clamp(currentLeft, minLeft, maxLeft);
|
|
115
|
+
tx = constrainedLeft - initialElementLeft;
|
|
116
|
+
}
|
|
117
|
+
return { tx, ty, blend, finalWidth };
|
|
118
|
+
};
|
|
52
119
|
const updateTransform = (scale) => {
|
|
53
|
-
|
|
120
|
+
currentScale = scale;
|
|
121
|
+
const { tx, ty } = calculateTransform(scale);
|
|
122
|
+
element.style.transformOrigin = "0 0";
|
|
123
|
+
element.style.transform = `translate(${tx}px, ${ty}px) scale(${scale})`;
|
|
54
124
|
};
|
|
55
125
|
const resetTransform = () => {
|
|
56
126
|
element.style.transform = "none";
|
|
57
127
|
element.style.transformOrigin = "0 0";
|
|
128
|
+
currentScale = 1;
|
|
58
129
|
};
|
|
59
|
-
const
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
if ((_a = e.srcEvent) == null ? void 0 : _a.cancelable) {
|
|
70
|
-
e.srcEvent.preventDefault();
|
|
71
|
-
e.srcEvent.stopPropagation();
|
|
130
|
+
const commitZoom = () => {
|
|
131
|
+
const { tx, finalWidth } = calculateTransform(currentScale);
|
|
132
|
+
const delta = (currentScale - 1) * initialZoom;
|
|
133
|
+
let anchorX;
|
|
134
|
+
let anchorY = pointerContainerY;
|
|
135
|
+
if (finalWidth <= layoutWidth) {
|
|
136
|
+
anchorX = layoutCenterX;
|
|
137
|
+
} else {
|
|
138
|
+
const scaleDiff = 1 - currentScale;
|
|
139
|
+
anchorX = Math.abs(scaleDiff) > 1e-3 ? initialElementLeft + tx / scaleDiff : pointerContainerX;
|
|
72
140
|
}
|
|
141
|
+
zoomScope.requestZoomBy(delta, { vx: anchorX, vy: anchorY });
|
|
142
|
+
resetTransform();
|
|
143
|
+
initialZoom = 0;
|
|
73
144
|
};
|
|
74
|
-
const
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
145
|
+
const initializeGestureState = (clientX, clientY) => {
|
|
146
|
+
const containerRect = container.getBoundingClientRect();
|
|
147
|
+
const innerRect = element.getBoundingClientRect();
|
|
148
|
+
currentGap = viewportGap;
|
|
149
|
+
initialElementWidth = innerRect.width;
|
|
150
|
+
initialElementHeight = innerRect.height;
|
|
151
|
+
initialElementLeft = innerRect.left - containerRect.left;
|
|
152
|
+
initialElementTop = innerRect.top - containerRect.top;
|
|
153
|
+
containerRectWidth = containerRect.width;
|
|
154
|
+
containerRectHeight = containerRect.height;
|
|
155
|
+
layoutWidth = container.clientWidth;
|
|
156
|
+
layoutCenterX = container.clientLeft + layoutWidth / 2;
|
|
157
|
+
const rawPointerLocalX = clientX - innerRect.left;
|
|
158
|
+
pointerLocalY = clientY - innerRect.top;
|
|
159
|
+
pointerContainerX = clientX - containerRect.left;
|
|
160
|
+
pointerContainerY = clientY - containerRect.top;
|
|
161
|
+
if (initialElementWidth < layoutWidth) {
|
|
162
|
+
pivotLocalX = pointerContainerX * initialElementWidth / layoutWidth;
|
|
163
|
+
} else {
|
|
164
|
+
pivotLocalX = rawPointerLocalX;
|
|
80
165
|
}
|
|
81
166
|
};
|
|
82
|
-
const
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
167
|
+
const handleTouchStart = (e) => {
|
|
168
|
+
if (e.touches.length !== 2) return;
|
|
169
|
+
isPinching = true;
|
|
170
|
+
initialZoom = getState().currentZoomLevel;
|
|
171
|
+
initialDistance = getTouchDistance(e.touches);
|
|
172
|
+
const center = getTouchCenter(e.touches);
|
|
173
|
+
initializeGestureState(center.x, center.y);
|
|
174
|
+
e.preventDefault();
|
|
87
175
|
};
|
|
88
|
-
const
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
176
|
+
const handleTouchMove = (e) => {
|
|
177
|
+
if (!isPinching || e.touches.length !== 2) return;
|
|
178
|
+
const currentDistance = getTouchDistance(e.touches);
|
|
179
|
+
const scale = currentDistance / initialDistance;
|
|
180
|
+
updateTransform(scale);
|
|
181
|
+
e.preventDefault();
|
|
182
|
+
};
|
|
183
|
+
const handleTouchEnd = (e) => {
|
|
184
|
+
if (!isPinching) return;
|
|
185
|
+
if (e.touches.length >= 2) return;
|
|
186
|
+
isPinching = false;
|
|
187
|
+
commitZoom();
|
|
188
|
+
};
|
|
189
|
+
const handleWheel = (e) => {
|
|
190
|
+
if (!e.ctrlKey && !e.metaKey) return;
|
|
191
|
+
e.preventDefault();
|
|
192
|
+
if (wheelZoomTimeout === null) {
|
|
193
|
+
initialZoom = getState().currentZoomLevel;
|
|
194
|
+
accumulatedWheelScale = 1;
|
|
195
|
+
initializeGestureState(e.clientX, e.clientY);
|
|
196
|
+
} else {
|
|
197
|
+
clearTimeout(wheelZoomTimeout);
|
|
109
198
|
}
|
|
199
|
+
const zoomFactor = 1 - e.deltaY * 0.01;
|
|
200
|
+
accumulatedWheelScale *= zoomFactor;
|
|
201
|
+
accumulatedWheelScale = Math.max(0.1, Math.min(10, accumulatedWheelScale));
|
|
202
|
+
updateTransform(accumulatedWheelScale);
|
|
203
|
+
wheelZoomTimeout = setTimeout(() => {
|
|
204
|
+
wheelZoomTimeout = null;
|
|
205
|
+
commitZoom();
|
|
206
|
+
accumulatedWheelScale = 1;
|
|
207
|
+
}, 150);
|
|
110
208
|
};
|
|
111
|
-
|
|
209
|
+
const unsubZoom = zoomScope.onStateChange(() => updateMargin());
|
|
210
|
+
const resizeObserver = new ResizeObserver(() => updateMargin());
|
|
211
|
+
resizeObserver.observe(element);
|
|
212
|
+
resizeObserver.observe(container);
|
|
213
|
+
updateMargin();
|
|
214
|
+
if (enablePinch) {
|
|
215
|
+
container.addEventListener("touchstart", handleTouchStart, { passive: false });
|
|
216
|
+
container.addEventListener("touchmove", handleTouchMove, { passive: false });
|
|
217
|
+
container.addEventListener("touchend", handleTouchEnd);
|
|
218
|
+
container.addEventListener("touchcancel", handleTouchEnd);
|
|
219
|
+
}
|
|
220
|
+
if (enableWheel) {
|
|
221
|
+
container.addEventListener("wheel", handleWheel, { passive: false });
|
|
222
|
+
}
|
|
112
223
|
return () => {
|
|
113
|
-
|
|
224
|
+
if (enablePinch) {
|
|
225
|
+
container.removeEventListener("touchstart", handleTouchStart);
|
|
226
|
+
container.removeEventListener("touchmove", handleTouchMove);
|
|
227
|
+
container.removeEventListener("touchend", handleTouchEnd);
|
|
228
|
+
container.removeEventListener("touchcancel", handleTouchEnd);
|
|
229
|
+
}
|
|
230
|
+
if (enableWheel) {
|
|
231
|
+
container.removeEventListener("wheel", handleWheel);
|
|
232
|
+
}
|
|
233
|
+
if (wheelZoomTimeout) {
|
|
234
|
+
clearTimeout(wheelZoomTimeout);
|
|
235
|
+
}
|
|
236
|
+
unsubZoom();
|
|
237
|
+
resizeObserver.disconnect();
|
|
114
238
|
resetTransform();
|
|
239
|
+
element.style.marginLeft = "";
|
|
115
240
|
};
|
|
116
241
|
}
|
|
117
|
-
function
|
|
242
|
+
function useZoomGesture(documentId, options = {}) {
|
|
118
243
|
const { provides: viewportProvides } = useCapability("viewport");
|
|
119
244
|
const { provides: zoomProvides } = useZoomCapability();
|
|
245
|
+
const viewportElementRef = inject("viewport-element");
|
|
120
246
|
const elementRef = ref(null);
|
|
121
247
|
let cleanup;
|
|
122
248
|
watch(
|
|
123
|
-
[
|
|
124
|
-
|
|
249
|
+
[
|
|
250
|
+
elementRef,
|
|
251
|
+
viewportProvides,
|
|
252
|
+
zoomProvides,
|
|
253
|
+
() => toValue(documentId),
|
|
254
|
+
() => toValue(options.enablePinch ?? true),
|
|
255
|
+
() => toValue(options.enableWheel ?? true)
|
|
256
|
+
],
|
|
257
|
+
([element, viewport, zoom, docId, enablePinch, enableWheel]) => {
|
|
125
258
|
if (cleanup) {
|
|
126
259
|
cleanup();
|
|
127
260
|
cleanup = void 0;
|
|
128
261
|
}
|
|
129
|
-
|
|
262
|
+
const container = viewportElementRef == null ? void 0 : viewportElementRef.value;
|
|
263
|
+
if (!element || !container || !zoom) {
|
|
130
264
|
return;
|
|
131
265
|
}
|
|
132
|
-
cleanup =
|
|
266
|
+
cleanup = setupZoomGestures({
|
|
133
267
|
element,
|
|
268
|
+
container,
|
|
134
269
|
documentId: docId,
|
|
135
|
-
|
|
136
|
-
|
|
270
|
+
zoomProvides: zoom,
|
|
271
|
+
viewportGap: (viewport == null ? void 0 : viewport.getViewportGap()) || 0,
|
|
272
|
+
options: { enablePinch, enableWheel }
|
|
137
273
|
});
|
|
138
274
|
},
|
|
139
275
|
{ immediate: true }
|
|
@@ -203,23 +339,26 @@ const _sfc_main$1 = /* @__PURE__ */ defineComponent({
|
|
|
203
339
|
}
|
|
204
340
|
});
|
|
205
341
|
const _sfc_main = /* @__PURE__ */ defineComponent({
|
|
206
|
-
__name: "
|
|
342
|
+
__name: "zoom-gesture-wrapper",
|
|
207
343
|
props: {
|
|
208
|
-
documentId: {}
|
|
344
|
+
documentId: {},
|
|
345
|
+
enablePinch: { type: Boolean, default: true },
|
|
346
|
+
enableWheel: { type: Boolean, default: true }
|
|
209
347
|
},
|
|
210
348
|
setup(__props) {
|
|
211
349
|
const props = __props;
|
|
212
|
-
const { elementRef } =
|
|
350
|
+
const { elementRef } = useZoomGesture(() => props.documentId, {
|
|
351
|
+
enablePinch: toRef(() => props.enablePinch),
|
|
352
|
+
enableWheel: toRef(() => props.enableWheel)
|
|
353
|
+
});
|
|
213
354
|
return (_ctx, _cache) => {
|
|
214
355
|
return openBlock(), createElementBlock("div", mergeProps({
|
|
215
356
|
ref_key: "elementRef",
|
|
216
357
|
ref: elementRef,
|
|
217
358
|
style: {
|
|
218
|
-
display: "block",
|
|
219
|
-
width: "fit-content",
|
|
359
|
+
display: "inline-block",
|
|
220
360
|
overflow: "visible",
|
|
221
|
-
boxSizing: "border-box"
|
|
222
|
-
margin: "0px auto"
|
|
361
|
+
boxSizing: "border-box"
|
|
223
362
|
}
|
|
224
363
|
}, _ctx.$attrs), [
|
|
225
364
|
renderSlot(_ctx.$slots, "default")
|
|
@@ -229,10 +368,10 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
|
|
|
229
368
|
});
|
|
230
369
|
export {
|
|
231
370
|
_sfc_main$1 as MarqueeZoom,
|
|
232
|
-
_sfc_main as
|
|
233
|
-
usePinch,
|
|
371
|
+
_sfc_main as ZoomGestureWrapper,
|
|
234
372
|
useZoom,
|
|
235
373
|
useZoomCapability,
|
|
374
|
+
useZoomGesture,
|
|
236
375
|
useZoomPlugin
|
|
237
376
|
};
|
|
238
377
|
//# sourceMappingURL=index.js.map
|
package/dist/vue/index.js.map
CHANGED
|
@@ -1 +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, watch, readonly, computed, toValue, type MaybeRefOrGetter } from 'vue';\nimport { useCapability, usePlugin } from '@embedpdf/core/vue';\nimport { initialDocumentState, ZoomPlugin, ZoomDocumentState } from '@embedpdf/plugin-zoom';\n\nexport const useZoomCapability = () => useCapability<ZoomPlugin>(ZoomPlugin.id);\nexport const useZoomPlugin = () => usePlugin<ZoomPlugin>(ZoomPlugin.id);\n\n/**\n * Hook for zoom state for a specific document\n * @param documentId Document ID (can be ref, computed, getter, or plain value)\n */\nexport const useZoom = (documentId: MaybeRefOrGetter<string>) => {\n const { provides } = useZoomCapability();\n const state = ref<ZoomDocumentState>(initialDocumentState);\n\n watch(\n [provides, () => toValue(documentId)],\n ([providesValue, docId], _, onCleanup) => {\n if (!providesValue) {\n state.value = initialDocumentState;\n return;\n }\n\n const scope = providesValue.forDocument(docId);\n\n // Get initial state\n state.value = scope.getState();\n\n // Subscribe to state changes\n const unsubscribe = scope.onStateChange((newState) => {\n state.value = newState;\n });\n\n onCleanup(unsubscribe);\n },\n { immediate: true },\n );\n\n // Return a computed ref for the scoped capability\n const scopedProvides = computed(() => {\n const docId = toValue(documentId);\n return provides.value?.forDocument(docId) ?? null;\n });\n\n return {\n state: readonly(state),\n provides: scopedProvides,\n };\n};\n","import type { ViewportCapability } from '@embedpdf/plugin-viewport';\nimport type { ZoomCapability } from '@embedpdf/plugin-zoom';\n\nexport interface PinchZoomDeps {\n element: HTMLDivElement;\n documentId: string;\n viewportProvides: ViewportCapability;\n zoomProvides: ZoomCapability;\n}\n\nexport function setupPinchZoom({\n element,\n documentId,\n viewportProvides,\n zoomProvides,\n}: PinchZoomDeps) {\n if (typeof window === 'undefined') {\n return () => {};\n }\n\n let hammer: any | undefined;\n let initialZoom = 0;\n let lastCenter = { x: 0, y: 0 };\n\n const viewportScope = viewportProvides.forDocument(documentId);\n const zoomScope = zoomProvides.forDocument(documentId);\n\n const getState = () => zoomScope.getState();\n\n const updateTransform = (scale: number) => {\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 = viewportScope.getBoundingRect();\n\n lastCenter = {\n x: e.center.x - contRect.origin.x,\n y: e.center.y - contRect.origin.y,\n };\n\n const innerRect = element.getBoundingClientRect();\n element.style.transformOrigin = `${e.center.x - innerRect.left}px ${e.center.y - innerRect.top}px`;\n\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);\n if (e.srcEvent?.cancelable) {\n e.srcEvent.preventDefault();\n e.srcEvent.stopPropagation();\n }\n };\n\n const pinchEnd = (e: HammerInput) => {\n const delta = (e.scale - 1) * initialZoom;\n zoomScope.requestZoomBy(delta, { vx: lastCenter.x, vy: lastCenter.y });\n\n resetTransform();\n initialZoom = 0;\n };\n\n const setupHammer = async () => {\n try {\n const Hammer = (await import('hammerjs')).default;\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',\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}\n","import { ref, watch, toValue, type MaybeRefOrGetter } 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\n/**\n * Hook for setting up pinch-to-zoom functionality on an element\n * @param documentId Document ID (can be ref, computed, getter, or plain value)\n */\nexport function usePinch(documentId: MaybeRefOrGetter<string>) {\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 watch(\n [elementRef, viewportProvides, zoomProvides, () => toValue(documentId)],\n ([element, viewport, zoom, docId]) => {\n // Clean up previous setup\n if (cleanup) {\n cleanup();\n cleanup = undefined;\n }\n\n // Setup new pinch zoom if all dependencies are available\n if (!element || !viewport || !zoom) {\n return;\n }\n\n cleanup = setupPinchZoom({\n element,\n documentId: docId,\n viewportProvides: viewport,\n zoomProvides: zoom,\n });\n },\n { immediate: true },\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 * actualScale}px`,\n top: `${rect.origin.y * actualScale}px`,\n width: `${rect.size.width * actualScale}px`,\n height: `${rect.size.height * actualScale}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, computed, watch } from 'vue';\nimport type { Rect } from '@embedpdf/models';\nimport { useDocumentState } from '@embedpdf/core/vue';\nimport { useZoomCapability } from '../hooks';\n\ninterface MarqueeZoomProps {\n /** The ID of the document */\n documentId: string;\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 documentState = useDocumentState(() => props.documentId);\nconst rect = ref<Rect | null>(null);\n\nconst actualScale = computed(() => {\n if (props.scale !== undefined) return props.scale;\n return documentState.value?.scale ?? 1;\n});\n\nwatch(\n [zoomPlugin, () => props.documentId, () => props.pageIndex, actualScale],\n ([plugin, docId, pageIdx, scale], _, onCleanup) => {\n if (!plugin) {\n rect.value = null;\n return;\n }\n\n const unregister = plugin.registerMarqueeOnPage({\n documentId: docId,\n pageIndex: pageIdx,\n scale,\n callback: {\n onPreview: (newRect) => {\n rect.value = newRect;\n },\n },\n });\n\n onCleanup(() => {\n unregister?.();\n });\n },\n { immediate: true },\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\ninterface Props {\n documentId: string;\n}\n\nconst props = defineProps<Props>();\n\nconst { elementRef } = usePinch(props.documentId);\n</script>\n"],"names":["_createElementBlock","_normalizeStyle","_openBlock","_mergeProps","$attrs","_renderSlot"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","sources":["../../src/vue/hooks/use-zoom.ts","../../src/shared/utils/zoom-gesture-logic.ts","../../src/vue/hooks/use-zoom-gesture.ts","../../src/vue/components/marquee-zoom.vue","../../src/vue/components/zoom-gesture-wrapper.vue"],"sourcesContent":["import { ref, watch, readonly, computed, toValue, type MaybeRefOrGetter } from 'vue';\nimport { useCapability, usePlugin } from '@embedpdf/core/vue';\nimport { initialDocumentState, ZoomPlugin, ZoomDocumentState } from '@embedpdf/plugin-zoom';\n\nexport const useZoomCapability = () => useCapability<ZoomPlugin>(ZoomPlugin.id);\nexport const useZoomPlugin = () => usePlugin<ZoomPlugin>(ZoomPlugin.id);\n\n/**\n * Hook for zoom state for a specific document\n * @param documentId Document ID (can be ref, computed, getter, or plain value)\n */\nexport const useZoom = (documentId: MaybeRefOrGetter<string>) => {\n const { provides } = useZoomCapability();\n const state = ref<ZoomDocumentState>(initialDocumentState);\n\n watch(\n [provides, () => toValue(documentId)],\n ([providesValue, docId], _, onCleanup) => {\n if (!providesValue) {\n state.value = initialDocumentState;\n return;\n }\n\n const scope = providesValue.forDocument(docId);\n\n // Get initial state\n state.value = scope.getState();\n\n // Subscribe to state changes\n const unsubscribe = scope.onStateChange((newState) => {\n state.value = newState;\n });\n\n onCleanup(unsubscribe);\n },\n { immediate: true },\n );\n\n // Return a computed ref for the scoped capability\n const scopedProvides = computed(() => {\n const docId = toValue(documentId);\n return provides.value?.forDocument(docId) ?? null;\n });\n\n return {\n state: readonly(state),\n provides: scopedProvides,\n };\n};\n","import type { ZoomCapability } from '@embedpdf/plugin-zoom';\n\nexport interface ZoomGestureOptions {\n /** Enable pinch-to-zoom gesture (default: true) */\n enablePinch?: boolean;\n /** Enable wheel zoom with ctrl/cmd key (default: true) */\n enableWheel?: boolean;\n}\n\nexport interface ZoomGestureDeps {\n element: HTMLDivElement;\n /** Viewport container element for attaching events */\n container: HTMLElement;\n documentId: string;\n zoomProvides: ZoomCapability;\n /** Viewport gap in pixels (default: 0) */\n viewportGap?: number;\n options?: ZoomGestureOptions;\n}\n\nfunction getTouchDistance(touches: TouchList): number {\n const [t1, t2] = [touches[0], touches[1]];\n const dx = t2.clientX - t1.clientX;\n const dy = t2.clientY - t1.clientY;\n return Math.hypot(dx, dy);\n}\n\nfunction getTouchCenter(touches: TouchList): { x: number; y: number } {\n const [t1, t2] = [touches[0], touches[1]];\n return {\n x: (t1.clientX + t2.clientX) / 2,\n y: (t1.clientY + t2.clientY) / 2,\n };\n}\n\nexport function setupZoomGestures({\n element,\n container,\n documentId,\n zoomProvides,\n viewportGap = 0,\n options = {},\n}: ZoomGestureDeps) {\n const { enablePinch = true, enableWheel = true } = options;\n if (typeof window === 'undefined') {\n return () => {};\n }\n\n const zoomScope = zoomProvides.forDocument(documentId);\n const getState = () => zoomScope.getState();\n\n // Shared state\n let initialZoom = 0;\n let currentScale = 1;\n let isPinching = false;\n let initialDistance = 0;\n\n // Wheel state\n let wheelZoomTimeout: ReturnType<typeof setTimeout> | null = null;\n let accumulatedWheelScale = 1;\n\n // Gesture state\n let initialElementWidth = 0;\n let initialElementHeight = 0;\n let initialElementLeft = 0;\n let initialElementTop = 0;\n\n // Container Dimensions (Bounding Box)\n let containerRectWidth = 0;\n let containerRectHeight = 0;\n\n // Layout Dimensions (Client Box from Metrics)\n let layoutWidth = 0;\n let layoutCenterX = 0;\n\n let pointerLocalY = 0;\n let pointerContainerX = 0;\n let pointerContainerY = 0;\n\n let currentGap = 0;\n let pivotLocalX = 0;\n\n const clamp = (val: number, min: number, max: number) => Math.min(Math.max(val, min), max);\n\n // --- Margin calculation ---\n const updateMargin = () => {\n const availableWidth = container.clientWidth - 2 * viewportGap;\n const elementWidth = element.offsetWidth;\n\n const newMargin = elementWidth < availableWidth ? (availableWidth - elementWidth) / 2 : 0;\n element.style.marginLeft = `${newMargin}px`;\n };\n\n const calculateTransform = (scale: number) => {\n const finalWidth = initialElementWidth * scale;\n const finalHeight = initialElementHeight * scale;\n\n let ty = pointerLocalY * (1 - scale);\n\n const targetX = layoutCenterX - finalWidth / 2;\n const txCenter = targetX - initialElementLeft;\n const txMouse = pointerContainerX - pivotLocalX * scale - initialElementLeft;\n\n const overflow = Math.max(0, finalWidth - layoutWidth);\n const blendRange = layoutWidth * 0.3;\n const blend = Math.min(1, overflow / blendRange);\n\n let tx = txCenter + (txMouse - txCenter) * blend;\n\n const safeHeight = containerRectHeight - currentGap * 2;\n if (finalHeight > safeHeight) {\n const currentTop = initialElementTop + ty;\n const maxTop = currentGap;\n const minTop = containerRectHeight - currentGap - finalHeight;\n const constrainedTop = clamp(currentTop, minTop, maxTop);\n ty = constrainedTop - initialElementTop;\n }\n\n const safeWidth = containerRectWidth - currentGap * 2;\n if (finalWidth > safeWidth) {\n const currentLeft = initialElementLeft + tx;\n const maxLeft = currentGap;\n const minLeft = containerRectWidth - currentGap - finalWidth;\n const constrainedLeft = clamp(currentLeft, minLeft, maxLeft);\n tx = constrainedLeft - initialElementLeft;\n }\n\n return { tx, ty, blend, finalWidth };\n };\n\n const updateTransform = (scale: number) => {\n currentScale = scale;\n const { tx, ty } = calculateTransform(scale);\n element.style.transformOrigin = '0 0';\n element.style.transform = `translate(${tx}px, ${ty}px) scale(${scale})`;\n };\n\n const resetTransform = () => {\n element.style.transform = 'none';\n element.style.transformOrigin = '0 0';\n currentScale = 1;\n };\n\n const commitZoom = () => {\n const { tx, finalWidth } = calculateTransform(currentScale);\n const delta = (currentScale - 1) * initialZoom;\n\n let anchorX: number;\n let anchorY: number = pointerContainerY;\n\n if (finalWidth <= layoutWidth) {\n anchorX = layoutCenterX;\n } else {\n const scaleDiff = 1 - currentScale;\n anchorX =\n Math.abs(scaleDiff) > 0.001 ? initialElementLeft + tx / scaleDiff : pointerContainerX;\n }\n\n zoomScope.requestZoomBy(delta, { vx: anchorX, vy: anchorY });\n resetTransform();\n initialZoom = 0;\n };\n\n const initializeGestureState = (clientX: number, clientY: number) => {\n const containerRect = container.getBoundingClientRect();\n const innerRect = element.getBoundingClientRect();\n\n currentGap = viewportGap;\n initialElementWidth = innerRect.width;\n initialElementHeight = innerRect.height;\n initialElementLeft = innerRect.left - containerRect.left;\n initialElementTop = innerRect.top - containerRect.top;\n\n containerRectWidth = containerRect.width;\n containerRectHeight = containerRect.height;\n\n // Layout dimensions from container's client area\n layoutWidth = container.clientWidth;\n layoutCenterX = container.clientLeft + layoutWidth / 2;\n\n const rawPointerLocalX = clientX - innerRect.left;\n pointerLocalY = clientY - innerRect.top;\n pointerContainerX = clientX - containerRect.left;\n pointerContainerY = clientY - containerRect.top;\n\n if (initialElementWidth < layoutWidth) {\n pivotLocalX = (pointerContainerX * initialElementWidth) / layoutWidth;\n } else {\n pivotLocalX = rawPointerLocalX;\n }\n };\n\n // --- Handlers ---\n const handleTouchStart = (e: TouchEvent) => {\n if (e.touches.length !== 2) return;\n isPinching = true;\n initialZoom = getState().currentZoomLevel;\n initialDistance = getTouchDistance(e.touches);\n const center = getTouchCenter(e.touches);\n initializeGestureState(center.x, center.y);\n e.preventDefault();\n };\n\n const handleTouchMove = (e: TouchEvent) => {\n if (!isPinching || e.touches.length !== 2) return;\n const currentDistance = getTouchDistance(e.touches);\n const scale = currentDistance / initialDistance;\n updateTransform(scale);\n e.preventDefault();\n };\n\n const handleTouchEnd = (e: TouchEvent) => {\n if (!isPinching) return;\n if (e.touches.length >= 2) return;\n isPinching = false;\n commitZoom();\n };\n\n const handleWheel = (e: WheelEvent) => {\n if (!e.ctrlKey && !e.metaKey) return;\n e.preventDefault();\n\n if (wheelZoomTimeout === null) {\n initialZoom = getState().currentZoomLevel;\n accumulatedWheelScale = 1;\n initializeGestureState(e.clientX, e.clientY);\n } else {\n clearTimeout(wheelZoomTimeout);\n }\n\n const zoomFactor = 1 - e.deltaY * 0.01;\n accumulatedWheelScale *= zoomFactor;\n accumulatedWheelScale = Math.max(0.1, Math.min(10, accumulatedWheelScale));\n updateTransform(accumulatedWheelScale);\n\n wheelZoomTimeout = setTimeout(() => {\n wheelZoomTimeout = null;\n commitZoom();\n accumulatedWheelScale = 1;\n }, 150);\n };\n\n // Subscribe to zoom changes to update margin\n const unsubZoom = zoomScope.onStateChange(() => updateMargin());\n\n // Use ResizeObserver to update margin when element or container size changes\n const resizeObserver = new ResizeObserver(() => updateMargin());\n resizeObserver.observe(element);\n resizeObserver.observe(container);\n\n // Initial margin calculation\n updateMargin();\n\n // Attach events to the viewport container for better UX\n // (gestures work anywhere in viewport, not just on the PDF)\n if (enablePinch) {\n container.addEventListener('touchstart', handleTouchStart, { passive: false });\n container.addEventListener('touchmove', handleTouchMove, { passive: false });\n container.addEventListener('touchend', handleTouchEnd);\n container.addEventListener('touchcancel', handleTouchEnd);\n }\n if (enableWheel) {\n container.addEventListener('wheel', handleWheel, { passive: false });\n }\n\n return () => {\n if (enablePinch) {\n container.removeEventListener('touchstart', handleTouchStart);\n container.removeEventListener('touchmove', handleTouchMove);\n container.removeEventListener('touchend', handleTouchEnd);\n container.removeEventListener('touchcancel', handleTouchEnd);\n }\n if (enableWheel) {\n container.removeEventListener('wheel', handleWheel);\n }\n if (wheelZoomTimeout) {\n clearTimeout(wheelZoomTimeout);\n }\n unsubZoom();\n resizeObserver.disconnect();\n resetTransform();\n element.style.marginLeft = '';\n };\n}\n","import { ref, watch, toValue, inject, type MaybeRefOrGetter, type Ref } from 'vue';\nimport { useCapability } from '@embedpdf/core/vue';\nimport type { ViewportPlugin, ViewportCapability } from '@embedpdf/plugin-viewport';\n\nimport { setupZoomGestures, type ZoomGestureOptions } from '../../shared/utils/zoom-gesture-logic';\nimport { useZoomCapability } from './use-zoom';\nimport type { ZoomCapability } from '../../lib/types';\n\nexport type { ZoomGestureOptions };\n\nexport interface UseZoomGestureOptions {\n /** Enable pinch-to-zoom gesture (default: true) */\n enablePinch?: MaybeRefOrGetter<boolean>;\n /** Enable wheel zoom with ctrl/cmd key (default: true) */\n enableWheel?: MaybeRefOrGetter<boolean>;\n}\n\n/**\n * Hook for setting up zoom gesture functionality (pinch and wheel zoom) on an element\n * @param documentId Document ID (can be ref, computed, getter, or plain value)\n * @param options Optional configuration for enabling/disabling gestures\n */\nexport function useZoomGesture(\n documentId: MaybeRefOrGetter<string>,\n options: UseZoomGestureOptions = {},\n) {\n const { provides: viewportProvides } = useCapability<ViewportPlugin>('viewport');\n const { provides: zoomProvides } = useZoomCapability();\n const viewportElementRef = inject<Ref<HTMLDivElement | null> | undefined>('viewport-element');\n const elementRef = ref<HTMLDivElement | null>(null);\n\n let cleanup: (() => void) | undefined;\n\n watch(\n [\n elementRef,\n viewportProvides,\n zoomProvides,\n () => toValue(documentId),\n () => toValue(options.enablePinch ?? true),\n () => toValue(options.enableWheel ?? true),\n ],\n ([element, viewport, zoom, docId, enablePinch, enableWheel]: [\n HTMLDivElement | null,\n ViewportCapability | null,\n ZoomCapability | null,\n string,\n boolean,\n boolean,\n ]) => {\n // Clean up previous setup\n if (cleanup) {\n cleanup();\n cleanup = undefined;\n }\n\n const container = viewportElementRef?.value;\n\n // Setup new zoom gestures if all dependencies are available\n if (!element || !container || !zoom) {\n return;\n }\n\n cleanup = setupZoomGestures({\n element,\n container,\n documentId: docId,\n zoomProvides: zoom,\n viewportGap: viewport?.getViewportGap() || 0,\n options: { enablePinch, enableWheel },\n });\n },\n { immediate: true },\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 * actualScale}px`,\n top: `${rect.origin.y * actualScale}px`,\n width: `${rect.size.width * actualScale}px`,\n height: `${rect.size.height * actualScale}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, computed, watch } from 'vue';\nimport type { Rect } from '@embedpdf/models';\nimport { useDocumentState } from '@embedpdf/core/vue';\nimport { useZoomCapability } from '../hooks';\n\ninterface MarqueeZoomProps {\n /** The ID of the document */\n documentId: string;\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 documentState = useDocumentState(() => props.documentId);\nconst rect = ref<Rect | null>(null);\n\nconst actualScale = computed(() => {\n if (props.scale !== undefined) return props.scale;\n return documentState.value?.scale ?? 1;\n});\n\nwatch(\n [zoomPlugin, () => props.documentId, () => props.pageIndex, actualScale],\n ([plugin, docId, pageIdx, scale], _, onCleanup) => {\n if (!plugin) {\n rect.value = null;\n return;\n }\n\n const unregister = plugin.registerMarqueeOnPage({\n documentId: docId,\n pageIndex: pageIdx,\n scale,\n callback: {\n onPreview: (newRect) => {\n rect.value = newRect;\n },\n },\n });\n\n onCleanup(() => {\n unregister?.();\n });\n },\n { immediate: true },\n);\n</script>\n","<template>\n <div\n ref=\"elementRef\"\n :style=\"{\n display: 'inline-block',\n overflow: 'visible',\n boxSizing: 'border-box',\n }\"\n v-bind=\"$attrs\"\n >\n <slot />\n </div>\n</template>\n\n<script setup lang=\"ts\">\nimport { toRef } from 'vue';\nimport { useZoomGesture } from '../hooks/use-zoom-gesture';\n\ninterface Props {\n documentId: string;\n /** Enable pinch-to-zoom gesture (default: true) */\n enablePinch?: boolean;\n /** Enable wheel zoom with ctrl/cmd key (default: true) */\n enableWheel?: boolean;\n}\n\nconst props = withDefaults(defineProps<Props>(), {\n enablePinch: true,\n enableWheel: true,\n});\n\nconst { elementRef } = useZoomGesture(() => props.documentId, {\n enablePinch: toRef(() => props.enablePinch),\n enableWheel: toRef(() => props.enableWheel),\n});\n</script>\n"],"names":["_createElementBlock","_normalizeStyle","_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": "2.0.0
|
|
3
|
+
"version": "2.0.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"main": "./dist/index.cjs",
|
|
@@ -35,19 +35,17 @@
|
|
|
35
35
|
}
|
|
36
36
|
},
|
|
37
37
|
"dependencies": {
|
|
38
|
-
"
|
|
39
|
-
"@embedpdf/models": "2.0.0-next.2"
|
|
38
|
+
"@embedpdf/models": "2.0.0"
|
|
40
39
|
},
|
|
41
40
|
"devDependencies": {
|
|
42
|
-
"@types/hammerjs": "^2.0.46",
|
|
43
41
|
"@types/react": "^18.2.0",
|
|
44
42
|
"typescript": "^5.0.0",
|
|
45
|
-
"@embedpdf/core": "2.0.0
|
|
46
|
-
"@embedpdf/plugin-
|
|
43
|
+
"@embedpdf/core": "2.0.0",
|
|
44
|
+
"@embedpdf/plugin-viewport": "2.0.0",
|
|
47
45
|
"@embedpdf/build": "1.1.0",
|
|
48
|
-
"@embedpdf/plugin-
|
|
49
|
-
"@embedpdf/plugin-
|
|
50
|
-
"@embedpdf/plugin-
|
|
46
|
+
"@embedpdf/plugin-spread": "2.0.0",
|
|
47
|
+
"@embedpdf/plugin-scroll": "2.0.0",
|
|
48
|
+
"@embedpdf/plugin-interaction-manager": "2.0.0"
|
|
51
49
|
},
|
|
52
50
|
"peerDependencies": {
|
|
53
51
|
"react": ">=16.8.0",
|
|
@@ -55,9 +53,9 @@
|
|
|
55
53
|
"preact": "^10.26.4",
|
|
56
54
|
"vue": ">=3.2.0",
|
|
57
55
|
"svelte": ">=5 <6",
|
|
58
|
-
"@embedpdf/
|
|
59
|
-
"@embedpdf/plugin-scroll": "2.0.0
|
|
60
|
-
"@embedpdf/
|
|
56
|
+
"@embedpdf/core": "2.0.0",
|
|
57
|
+
"@embedpdf/plugin-scroll": "2.0.0",
|
|
58
|
+
"@embedpdf/plugin-viewport": "2.0.0"
|
|
61
59
|
},
|
|
62
60
|
"files": [
|
|
63
61
|
"dist",
|