@@ -605,8 +605,19 @@ export default function startListeners() {
605605
606606 if ( event . deltaX !== undefined && event . deltaY !== undefined ) {
607607 // Modern browsers: event.deltaX, event.deltaY
608- deltaX = event . deltaX
609- deltaY = event . deltaY
608+ // Normalize by deltaMode: 0 = pixel, 1 = line, 2 = page
609+ let modeScale = 1
610+
611+ if ( event . deltaMode === 1 ) {
612+ // Lines → approximate pixels
613+ modeScale = 16
614+ } else if ( event . deltaMode === 2 ) {
615+ // Pages → approximate one viewport height
616+ modeScale = window . innerHeight
617+ }
618+
619+ deltaX = event . deltaX * modeScale
620+ deltaY = event . deltaY * modeScale
610621 } else if ( event . wheelDeltaX !== undefined && event . wheelDeltaY !== undefined ) {
611622 // Webkit browsers: wheelDeltaX, wheelDeltaY (inverted sign)
612623 deltaX = - event . wheelDeltaX
@@ -851,29 +862,42 @@ export function setZoomFromSlider(
851862 minZoom = 0.5 * DPR ,
852863 maxZoom = 4 * DPR
853864) {
854- if ( maxSliderValue === minSliderValue || maxZoom === minZoom ) return
865+ // Guard against invalid inputs and degenerate ranges
866+ const inputs = [ sliderValue , minSliderValue , maxSliderValue , minZoom , maxZoom ]
867+ if (
868+ ! inputs . every ( Number . isFinite ) ||
869+ maxSliderValue === minSliderValue ||
870+ maxZoom === minZoom
871+ ) {
872+ return
873+ }
855874
856875 // Normalize slider value to 0-1 range
857- const normalizedValue = ( sliderValue - minSliderValue ) / ( maxSliderValue - minSliderValue )
858-
876+ const normalizedValue =
877+ ( sliderValue - minSliderValue ) / ( maxSliderValue - minSliderValue )
878+
859879 // Map to zoom scale range
860880 const targetScale = minZoom + normalizedValue * ( maxZoom - minZoom )
861-
881+
862882 // Clamp to valid zoom range
863883 const clampedScale = Math . max ( minZoom , Math . min ( maxZoom , targetScale ) )
864-
884+
865885 // Calculate delta from current scale
866886 const scaleDelta = clampedScale - globalScope . scale
867-
887+
888+ // Avoid applying invalid or zero delta
889+ if ( ! Number . isFinite ( scaleDelta ) || scaleDelta === 0 ) return
890+
868891 // Apply zoom centered on viewport (method = 3)
869892 changeScale ( scaleDelta , 'zoomButton' , 'zoomButton' , 3 )
870-
893+
871894 // Update display
872895 gridUpdateSet ( true )
873896 updateCanvasSet ( true )
874897 scheduleUpdate ( )
875898}
876899
900+
877901/**
878902 * Get the current zoom level as a slider value
879903 * Inverse of setZoomFromSlider - converts internal scale to slider value
@@ -893,20 +917,27 @@ export function getZoomSliderValue(
893917 minZoom = 0.5 * DPR ,
894918 maxZoom = 4 * DPR
895919) {
896- if ( maxSliderValue === minSliderValue || maxZoom === minZoom ) {
920+ const inputs = [ minSliderValue , maxSliderValue , minZoom , maxZoom , globalScope . scale ]
921+ if (
922+ ! inputs . every ( Number . isFinite ) ||
923+ maxSliderValue === minSliderValue ||
924+ maxZoom === minZoom
925+ ) {
897926 return minSliderValue
898927 }
899928
900929 const currentScale = globalScope . scale
901-
930+
902931 // Clamp current scale to valid range
903932 const clampedScale = Math . max ( minZoom , Math . min ( maxZoom , currentScale ) )
904-
933+
905934 // Normalize scale to 0-1 range
906935 const normalizedScale = ( clampedScale - minZoom ) / ( maxZoom - minZoom )
907-
936+
908937 // Map to slider value range
909- const sliderValue = minSliderValue + normalizedScale * ( maxSliderValue - minSliderValue )
910-
938+ const sliderValue =
939+ minSliderValue + normalizedScale * ( maxSliderValue - minSliderValue )
940+
911941 return sliderValue
912942}
943+
0 commit comments