From 3fa71ec2dd475b7af1dfa96f1b87f6917dc64400 Mon Sep 17 00:00:00 2001 From: mitchjb-sos Date: Tue, 14 Apr 2026 17:04:17 +0000 Subject: [PATCH] Proposed fix for zoom out issue --- .../src/shared/components/zoom-gesture-wrapper.tsx | 7 +++++-- packages/plugin-zoom/src/shared/hooks/use-pinch-zoom.ts | 1 + .../plugin-zoom/src/shared/hooks/use-zoom-gesture.ts | 1 + .../plugin-zoom/src/shared/utils/pinch-zoom-logic.ts | 9 ++++++--- .../plugin-zoom/src/shared/utils/zoom-gesture-logic.ts | 9 ++++++--- .../src/svelte/components/ZoomGestureWrapper.svelte | 4 ++++ .../src/svelte/hooks/use-pinch-zoom.svelte.ts | 5 ++++- .../src/svelte/hooks/use-zoom-gesture.svelte.ts | 5 ++++- .../src/vue/components/zoom-gesture-wrapper.vue | 4 ++++ packages/plugin-zoom/src/vue/hooks/use-pinch-zoom.ts | 8 ++++++-- packages/plugin-zoom/src/vue/hooks/use-zoom-gesture.ts | 8 ++++++-- 11 files changed, 47 insertions(+), 14 deletions(-) diff --git a/packages/plugin-zoom/src/shared/components/zoom-gesture-wrapper.tsx b/packages/plugin-zoom/src/shared/components/zoom-gesture-wrapper.tsx index 245aa8cc0..a27373c6e 100644 --- a/packages/plugin-zoom/src/shared/components/zoom-gesture-wrapper.tsx +++ b/packages/plugin-zoom/src/shared/components/zoom-gesture-wrapper.tsx @@ -9,6 +9,8 @@ type ZoomGestureWrapperProps = Omit, 'style'> & { enablePinch?: boolean; /** Enable wheel zoom with ctrl/cmd key (default: true) */ enableWheel?: boolean; + /** Override wheel zoom step; 0.1 = 10% (default: 0.1) */ + zoomStep?: number; }; export function ZoomGestureWrapper({ @@ -17,11 +19,12 @@ export function ZoomGestureWrapper({ style, enablePinch = true, enableWheel = true, + zoomStep = 0.1, ...props }: ZoomGestureWrapperProps) { const options = useMemo( - () => ({ enablePinch, enableWheel }), - [enablePinch, enableWheel], + () => ({ enablePinch, enableWheel, zoomStep }), + [enablePinch, enableWheel, zoomStep], ); const { elementRef } = useZoomGesture(documentId, options); diff --git a/packages/plugin-zoom/src/shared/hooks/use-pinch-zoom.ts b/packages/plugin-zoom/src/shared/hooks/use-pinch-zoom.ts index 6b99a9344..9a72dbf11 100644 --- a/packages/plugin-zoom/src/shared/hooks/use-pinch-zoom.ts +++ b/packages/plugin-zoom/src/shared/hooks/use-pinch-zoom.ts @@ -36,6 +36,7 @@ export function useZoomGesture(documentId: string, options: ZoomGestureOptions = viewportElementRef, options.enablePinch, options.enableWheel, + options.zoomStep, ]); return { elementRef }; diff --git a/packages/plugin-zoom/src/shared/hooks/use-zoom-gesture.ts b/packages/plugin-zoom/src/shared/hooks/use-zoom-gesture.ts index a286f3ca0..c356199b8 100644 --- a/packages/plugin-zoom/src/shared/hooks/use-zoom-gesture.ts +++ b/packages/plugin-zoom/src/shared/hooks/use-zoom-gesture.ts @@ -37,6 +37,7 @@ export function useZoomGesture(documentId: string, options: ZoomGestureOptions = viewportElementRef, options.enablePinch, options.enableWheel, + options.zoomStep, ]); return { elementRef }; diff --git a/packages/plugin-zoom/src/shared/utils/pinch-zoom-logic.ts b/packages/plugin-zoom/src/shared/utils/pinch-zoom-logic.ts index 3d1873efe..996ce9b2c 100644 --- a/packages/plugin-zoom/src/shared/utils/pinch-zoom-logic.ts +++ b/packages/plugin-zoom/src/shared/utils/pinch-zoom-logic.ts @@ -6,6 +6,8 @@ export interface ZoomGestureOptions { enablePinch?: boolean; /** Enable wheel zoom with ctrl/cmd key (default: true) */ enableWheel?: boolean; + /** Override wheel zoom step; 0.1 = 10% (default: 0.1) */ + zoomStep?: number; } export interface ZoomGestureDeps { @@ -41,7 +43,7 @@ export function setupZoomGestures({ zoomProvides, options = {}, }: ZoomGestureDeps) { - const { enablePinch = true, enableWheel = true } = options; + const { enablePinch = true, enableWheel = true, zoomStep = 0.1 } = options; if (typeof window === 'undefined') { return () => {}; } @@ -244,9 +246,10 @@ export function setupZoomGestures({ clearTimeout(wheelZoomTimeout); } - const zoomFactor = 1 - e.deltaY * 0.01; + // Utilizing deltaY sign instead of raw value to eliminate discrepancies between browsers + const zoomFactor = 1 - Math.sign(e.deltaY) * zoomStep; // Should this use zoomStep configured by the plugin config? accumulatedWheelScale *= zoomFactor; - accumulatedWheelScale = Math.max(0.1, Math.min(10, accumulatedWheelScale)); + accumulatedWheelScale = clamp(accumulatedWheelScale, 0.1, 10); updateTransform(accumulatedWheelScale); wheelZoomTimeout = setTimeout(() => { diff --git a/packages/plugin-zoom/src/shared/utils/zoom-gesture-logic.ts b/packages/plugin-zoom/src/shared/utils/zoom-gesture-logic.ts index 49c002485..fd5867df5 100644 --- a/packages/plugin-zoom/src/shared/utils/zoom-gesture-logic.ts +++ b/packages/plugin-zoom/src/shared/utils/zoom-gesture-logic.ts @@ -5,6 +5,8 @@ export interface ZoomGestureOptions { enablePinch?: boolean; /** Enable wheel zoom with ctrl/cmd key (default: true) */ enableWheel?: boolean; + /** Override wheel zoom step; 0.1 = 10% (default: 0.1) */ + zoomStep?: number; } export interface ZoomGestureDeps { @@ -41,7 +43,7 @@ export function setupZoomGestures({ viewportGap = 0, options = {}, }: ZoomGestureDeps) { - const { enablePinch = true, enableWheel = true } = options; + const { enablePinch = true, enableWheel = true, zoomStep = 0.1 } = options; if (typeof window === 'undefined') { return () => {}; } @@ -228,9 +230,10 @@ export function setupZoomGestures({ clearTimeout(wheelZoomTimeout); } - const zoomFactor = 1 - e.deltaY * 0.01; + // Utilizing deltaY sign instead of raw value to eliminate discrepancies between browsers + const zoomFactor = 1 - Math.sign(e.deltaY) * zoomStep; // Should this use zoomStep configured by the plugin config? accumulatedWheelScale *= zoomFactor; - accumulatedWheelScale = Math.max(0.1, Math.min(10, accumulatedWheelScale)); + accumulatedWheelScale = clamp(accumulatedWheelScale, 0.1, 10); updateTransform(accumulatedWheelScale); wheelZoomTimeout = setTimeout(() => { diff --git a/packages/plugin-zoom/src/svelte/components/ZoomGestureWrapper.svelte b/packages/plugin-zoom/src/svelte/components/ZoomGestureWrapper.svelte index ea8f31713..848bf268c 100644 --- a/packages/plugin-zoom/src/svelte/components/ZoomGestureWrapper.svelte +++ b/packages/plugin-zoom/src/svelte/components/ZoomGestureWrapper.svelte @@ -11,6 +11,8 @@ enablePinch?: boolean; /** Enable wheel zoom with ctrl/cmd key (default: true) */ enableWheel?: boolean; + /** Override wheel zoom step; 0.1 = 10% (default: 0.1) */ + zoomStep?: number; }; let { @@ -19,12 +21,14 @@ class: propsClass, enablePinch = true, enableWheel = true, + zoomStep = 0.1, ...restProps }: ZoomGestureWrapperProps = $props(); const zoomGesture = useZoomGesture(() => documentId, { enablePinch: () => enablePinch, enableWheel: () => enableWheel, + zoomStep: () => zoomStep, }); diff --git a/packages/plugin-zoom/src/svelte/hooks/use-pinch-zoom.svelte.ts b/packages/plugin-zoom/src/svelte/hooks/use-pinch-zoom.svelte.ts index 30f239d52..cb524d5a0 100644 --- a/packages/plugin-zoom/src/svelte/hooks/use-pinch-zoom.svelte.ts +++ b/packages/plugin-zoom/src/svelte/hooks/use-pinch-zoom.svelte.ts @@ -14,6 +14,8 @@ export interface UseZoomGestureOptions { enablePinch?: () => boolean; /** Enable wheel zoom with ctrl/cmd key (default: true) */ enableWheel?: () => boolean; + /** Override wheel zoom step; 0.1 = 10% (default: 0.1) */ + zoomStep?: () => number; } /** @@ -36,6 +38,7 @@ export function useZoomGesture( const documentId = $derived(getDocumentId()); const enablePinch = $derived(options.enablePinch?.() ?? true); const enableWheel = $derived(options.enableWheel?.() ?? true); + const zoomStep = $derived(options.zoomStep?.() ?? 0.1); $effect(() => { const element = elementRef; @@ -63,7 +66,7 @@ export function useZoomGesture( documentId: docId, viewportProvides: viewport, zoomProvides: zoom, - options: { enablePinch: pinchEnabled, enableWheel: wheelEnabled }, + options: { enablePinch: pinchEnabled, enableWheel: wheelEnabled, zoomStep }, }); return () => { diff --git a/packages/plugin-zoom/src/svelte/hooks/use-zoom-gesture.svelte.ts b/packages/plugin-zoom/src/svelte/hooks/use-zoom-gesture.svelte.ts index eb5d051ca..3ab4ea009 100644 --- a/packages/plugin-zoom/src/svelte/hooks/use-zoom-gesture.svelte.ts +++ b/packages/plugin-zoom/src/svelte/hooks/use-zoom-gesture.svelte.ts @@ -14,6 +14,8 @@ export interface UseZoomGestureOptions { enablePinch?: () => boolean; /** Enable wheel zoom with ctrl/cmd key (default: true) */ enableWheel?: () => boolean; + /** Override wheel zoom step; 0.1 = 10% (default: 0.1) */ + zoomStep?: () => number; } /** @@ -36,6 +38,7 @@ export function useZoomGesture( const documentId = $derived(getDocumentId()); const enablePinch = $derived(options.enablePinch?.() ?? true); const enableWheel = $derived(options.enableWheel?.() ?? true); + const zoomStep = $derived(options.zoomStep?.() ?? 0.1); $effect(() => { const element = elementRef; @@ -63,7 +66,7 @@ export function useZoomGesture( documentId: docId, zoomProvides: zoom, viewportGap: viewport?.getViewportGap() || 0, - options: { enablePinch: pinchEnabled, enableWheel: wheelEnabled }, + options: { enablePinch: pinchEnabled, enableWheel: wheelEnabled, zoomStep }, }); return () => { diff --git a/packages/plugin-zoom/src/vue/components/zoom-gesture-wrapper.vue b/packages/plugin-zoom/src/vue/components/zoom-gesture-wrapper.vue index 346d4c7b1..5c23a7847 100644 --- a/packages/plugin-zoom/src/vue/components/zoom-gesture-wrapper.vue +++ b/packages/plugin-zoom/src/vue/components/zoom-gesture-wrapper.vue @@ -22,15 +22,19 @@ interface Props { enablePinch?: boolean; /** Enable wheel zoom with ctrl/cmd key (default: true) */ enableWheel?: boolean; + /** Override wheel zoom step; 0.1 = 10% (default: 0.1) */ + zoomStep?: number; } const props = withDefaults(defineProps(), { enablePinch: true, enableWheel: true, + zoomStep: 0.1, }); const { elementRef } = useZoomGesture(() => props.documentId, { enablePinch: toRef(() => props.enablePinch), enableWheel: toRef(() => props.enableWheel), + zoomStep: toRef(() => props.zoomStep), }); diff --git a/packages/plugin-zoom/src/vue/hooks/use-pinch-zoom.ts b/packages/plugin-zoom/src/vue/hooks/use-pinch-zoom.ts index a074d7dc3..c2f49e4de 100644 --- a/packages/plugin-zoom/src/vue/hooks/use-pinch-zoom.ts +++ b/packages/plugin-zoom/src/vue/hooks/use-pinch-zoom.ts @@ -13,6 +13,8 @@ export interface UseZoomGestureOptions { enablePinch?: MaybeRefOrGetter; /** Enable wheel zoom with ctrl/cmd key (default: true) */ enableWheel?: MaybeRefOrGetter; + /** Override wheel zoom step; 0.1 = 10% (default: 0.1) */ + zoomStep?: number; } /** @@ -39,14 +41,16 @@ export function useZoomGesture( () => toValue(documentId), () => toValue(options.enablePinch ?? true), () => toValue(options.enableWheel ?? true), + () => toValue(options.zoomStep ?? 0.1), ], - ([element, viewport, zoom, docId, enablePinch, enableWheel]: [ + ([element, viewport, zoom, docId, enablePinch, enableWheel, zoomStep]: [ HTMLDivElement | null, ViewportCapability | null, ZoomCapability | null, string, boolean, boolean, + number, ]) => { // Clean up previous setup if (cleanup) { @@ -67,7 +71,7 @@ export function useZoomGesture( documentId: docId, viewportProvides: viewport, zoomProvides: zoom, - options: { enablePinch, enableWheel }, + options: { enablePinch, enableWheel, zoomStep }, }); }, { immediate: true }, diff --git a/packages/plugin-zoom/src/vue/hooks/use-zoom-gesture.ts b/packages/plugin-zoom/src/vue/hooks/use-zoom-gesture.ts index 835d69469..10293fb9c 100644 --- a/packages/plugin-zoom/src/vue/hooks/use-zoom-gesture.ts +++ b/packages/plugin-zoom/src/vue/hooks/use-zoom-gesture.ts @@ -13,6 +13,8 @@ export interface UseZoomGestureOptions { enablePinch?: MaybeRefOrGetter; /** Enable wheel zoom with ctrl/cmd key (default: true) */ enableWheel?: MaybeRefOrGetter; + /** Override wheel zoom step; 0.1 = 10% (default: 0.1) */ + zoomStep?: number; } /** @@ -39,14 +41,16 @@ export function useZoomGesture( () => toValue(documentId), () => toValue(options.enablePinch ?? true), () => toValue(options.enableWheel ?? true), + () => toValue(options.zoomStep ?? 0.1), ], - ([element, viewport, zoom, docId, enablePinch, enableWheel]: [ + ([element, viewport, zoom, docId, enablePinch, enableWheel, zoomStep]: [ HTMLDivElement | null, ViewportCapability | null, ZoomCapability | null, string, boolean, boolean, + number, ]) => { // Clean up previous setup if (cleanup) { @@ -67,7 +71,7 @@ export function useZoomGesture( documentId: docId, zoomProvides: zoom, viewportGap: viewport?.getViewportGap() || 0, - options: { enablePinch, enableWheel }, + options: { enablePinch, enableWheel, zoomStep }, }); }, { immediate: true },