kinetic-slider
Version:
A WebGL-powered kinetic slider component using PIXI.js
1 lines • 20 kB
Source Map (JSON)
{"version":3,"file":"useMouseDrag.cjs","sources":["../../../src/hooks/useMouseDrag.ts"],"sourcesContent":["import { useEffect, useRef, useCallback, type RefObject } from \"react\";\nimport { Sprite } from \"pixi.js\";\nimport { gsap } from \"gsap\";\nimport ResourceManager from '../managers/ResourceManager';\n\n// Development environment check\nconst isDevelopment = import.meta.env?.MODE === 'development';\n\ninterface UseMouseDragProps {\n sliderRef: RefObject<HTMLDivElement | null>;\n slidesRef: RefObject<Sprite[]>;\n currentIndex: RefObject<number>;\n swipeScaleIntensity: number;\n swipeDistance: number;\n onSwipeLeft: () => void;\n onSwipeRight: () => void;\n resourceManager?: ResourceManager | null;\n}\n\n/**\n * Hook to handle mouse drag interactions for slides\n * Fully optimized with:\n * - Batch animation processing\n * - Comprehensive error handling\n * - Memory leak prevention\n * - Performance optimizations\n * - Throttled event handling\n */\nconst useMouseDrag = ({\n sliderRef,\n slidesRef,\n currentIndex,\n swipeScaleIntensity,\n swipeDistance,\n onSwipeLeft,\n onSwipeRight,\n resourceManager\n }: UseMouseDragProps) => {\n // Track drag state with a ref to avoid re-renders\n const dragStateRef = useRef({\n isDragging: false,\n startX: 0,\n endX: 0,\n isAnimating: false,\n lastThrottleTime: 0,\n activeAnimations: [] as gsap.core.Tween[]\n });\n\n // Flag to track component mount state\n const isMountedRef = useRef(true);\n\n // Process a batch of animations using ResourceManager\n const processBatchAnimations = useCallback(() => {\n try {\n const { activeAnimations } = dragStateRef.current;\n\n // Skip if no resource manager or no animations\n if (!resourceManager || activeAnimations.length === 0) return;\n\n // Track all animations in batch\n resourceManager.trackAnimationBatch(activeAnimations);\n\n // Clear the array by setting length to 0 (more efficient than creating a new array)\n activeAnimations.length = 0;\n\n if (isDevelopment) {\n console.log('Processed batch animations for mouse drag');\n }\n } catch (error) {\n if (isDevelopment) {\n console.error('Error processing batch animations:', error);\n }\n // Clear array even on error\n dragStateRef.current.activeAnimations = [];\n }\n }, [resourceManager]);\n\n // Clean up any active animations\n const cleanupAnimations = useCallback(() => {\n try {\n const { activeAnimations } = dragStateRef.current;\n\n // Kill all active animations\n activeAnimations.forEach(tween => {\n if (tween && tween.isActive()) {\n tween.kill();\n }\n });\n\n // Clear the animations array\n activeAnimations.length = 0;\n\n // Reset animation state\n dragStateRef.current.isAnimating = false;\n } catch (error) {\n if (isDevelopment) {\n console.error('Error cleaning up animations:', error);\n }\n }\n }, []);\n\n // Handle mouse drag effects\n const handleDragEffect = useCallback((deltaX: number) => {\n try {\n if (!isMountedRef.current) return;\n\n const currentSlide = slidesRef.current[currentIndex.current];\n if (!currentSlide) return;\n\n // Calculate normalized scale factor based on drag distance\n const normalizedFactor = Math.min(Math.abs(deltaX) / swipeDistance, 1);\n const newScale = 1 + normalizedFactor * swipeScaleIntensity;\n\n // Clean up any existing animations\n cleanupAnimations();\n\n // Create and add the new animation to our active animations\n const dragTween = gsap.to(currentSlide.scale, {\n x: (currentSlide as any).baseScale * newScale,\n y: (currentSlide as any).baseScale * newScale,\n duration: 0.1,\n ease: \"power2.out\",\n onComplete: () => {\n // Re-track the sprite after animation\n if (resourceManager && currentSlide) {\n resourceManager.trackDisplayObject(currentSlide);\n }\n }\n });\n\n // Add to animations array\n dragStateRef.current.activeAnimations.push(dragTween);\n\n // Process animations in batch\n processBatchAnimations();\n } catch (error) {\n if (isDevelopment) {\n console.error('Error handling drag effect:', error);\n }\n }\n }, [\n slidesRef,\n currentIndex,\n swipeScaleIntensity,\n swipeDistance,\n cleanupAnimations,\n processBatchAnimations,\n resourceManager\n ]);\n\n // Reset slide scale after drag\n const resetSlideScale = useCallback(() => {\n try {\n if (!isMountedRef.current) return;\n\n const currentSlide = slidesRef.current[currentIndex.current];\n if (!currentSlide) return;\n\n // Clean up any existing animations\n cleanupAnimations();\n\n // Create and add the reset animation\n const resetTween = gsap.to(currentSlide.scale, {\n x: (currentSlide as any).baseScale,\n y: (currentSlide as any).baseScale,\n duration: 0.2,\n ease: \"power2.out\",\n onComplete: () => {\n // Re-track the sprite after animation\n if (resourceManager && currentSlide) {\n resourceManager.trackDisplayObject(currentSlide);\n }\n\n // Update state\n dragStateRef.current.isAnimating = false;\n }\n });\n\n // Add to animations array\n dragStateRef.current.activeAnimations.push(resetTween);\n\n // Process animations in batch\n processBatchAnimations();\n } catch (error) {\n if (isDevelopment) {\n console.error('Error resetting slide scale:', error);\n }\n // Ensure animation state is reset even on error\n dragStateRef.current.isAnimating = false;\n }\n }, [\n slidesRef,\n currentIndex,\n cleanupAnimations,\n processBatchAnimations,\n resourceManager\n ]);\n\n // Event handlers with memoization\n const handleMouseDown = useCallback((event: Event) => {\n try {\n const e = event as MouseEvent;\n e.preventDefault();\n\n // Set dragging state\n dragStateRef.current.isDragging = true;\n dragStateRef.current.startX = e.clientX;\n dragStateRef.current.endX = e.clientX;\n } catch (error) {\n if (isDevelopment) {\n console.error('Error in mouse down handler:', error);\n }\n }\n }, []);\n\n const handleMouseMove = useCallback((event: Event) => {\n try {\n // Skip if not dragging\n if (!dragStateRef.current.isDragging) return;\n\n const e = event as MouseEvent;\n e.preventDefault();\n\n // Apply throttling for performance (limit to 60fps)\n const now = Date.now();\n const throttleDelay = 16; // ~60fps\n if (now - dragStateRef.current.lastThrottleTime < throttleDelay) return;\n dragStateRef.current.lastThrottleTime = now;\n\n // Update drag end position\n dragStateRef.current.endX = e.clientX;\n\n // Calculate drag distance\n const deltaX = dragStateRef.current.endX - dragStateRef.current.startX;\n\n // Apply drag effect\n handleDragEffect(deltaX);\n } catch (error) {\n if (isDevelopment) {\n console.error('Error in mouse move handler:', error);\n }\n }\n }, [handleDragEffect]);\n\n const handleMouseUp = useCallback((event: Event) => {\n try {\n // Skip if not dragging\n if (!dragStateRef.current.isDragging) return;\n\n const e = event as MouseEvent;\n e.preventDefault();\n\n // Update state\n dragStateRef.current.isDragging = false;\n\n // Calculate final drag distance\n const deltaX = dragStateRef.current.endX - dragStateRef.current.startX;\n\n // Reset slide scale first\n resetSlideScale();\n\n // Handle swipe if distance is sufficient\n if (Math.abs(deltaX) > swipeDistance) {\n // Set small timeout to allow scale reset to complete\n setTimeout(() => {\n if (!isMountedRef.current) return;\n\n if (deltaX < 0) {\n onSwipeLeft();\n } else {\n onSwipeRight();\n }\n }, 50);\n }\n } catch (error) {\n if (isDevelopment) {\n console.error('Error in mouse up handler:', error);\n }\n // Reset dragging state even on error\n dragStateRef.current.isDragging = false;\n }\n }, [resetSlideScale, swipeDistance, onSwipeLeft, onSwipeRight]);\n\n const handleMouseLeave = useCallback((event: Event) => {\n try {\n // Skip if not dragging\n if (!dragStateRef.current.isDragging) return;\n\n const e = event as MouseEvent;\n e.preventDefault();\n\n // Update state\n dragStateRef.current.isDragging = false;\n\n // Reset slide scale\n resetSlideScale();\n } catch (error) {\n if (isDevelopment) {\n console.error('Error in mouse leave handler:', error);\n }\n // Reset dragging state even on error\n dragStateRef.current.isDragging = false;\n }\n }, [resetSlideScale]);\n\n // Set up event listeners with batch handling\n useEffect(() => {\n // Skip during server-side rendering\n if (typeof window === 'undefined') return;\n\n // Skip if slider reference is not available\n if (!sliderRef.current) return;\n\n try {\n const slider = sliderRef.current;\n\n // Update mounted ref\n isMountedRef.current = true;\n\n // Create event handler maps for batch registration\n const listeners = new Map<string, EventCallback[]>();\n\n // Maps for all our event types\n listeners.set('mousedown', [handleMouseDown]);\n listeners.set('mousemove', [handleMouseMove]);\n listeners.set('mouseup', [handleMouseUp]);\n listeners.set('mouseleave', [handleMouseLeave]);\n\n // Register event listeners - use batch if available\n if (resourceManager) {\n // Batch register all listeners\n resourceManager.addEventListenerBatch(slider, listeners);\n } else {\n // Fall back to individual registration\n slider.addEventListener('mousedown', handleMouseDown);\n slider.addEventListener('mousemove', handleMouseMove);\n slider.addEventListener('mouseup', handleMouseUp);\n slider.addEventListener('mouseleave', handleMouseLeave);\n }\n\n // Cleanup on unmount\n return () => {\n // Update mounted state immediately\n isMountedRef.current = false;\n\n try {\n // Clean up animations first\n cleanupAnimations();\n\n // ResourceManager will handle its own cleanup\n if (!resourceManager) {\n // Manual cleanup for each event\n slider.removeEventListener('mousedown', handleMouseDown);\n slider.removeEventListener('mousemove', handleMouseMove);\n slider.removeEventListener('mouseup', handleMouseUp);\n slider.removeEventListener('mouseleave', handleMouseLeave);\n }\n } catch (cleanupError) {\n if (isDevelopment) {\n console.error('Error during useMouseDrag cleanup:', cleanupError);\n }\n }\n };\n } catch (error) {\n if (isDevelopment) {\n console.error('Error setting up mouse drag handlers:', error);\n }\n // Return empty cleanup function\n return () => {};\n }\n }, [\n sliderRef,\n handleMouseDown,\n handleMouseMove,\n handleMouseUp,\n handleMouseLeave,\n cleanupAnimations,\n resourceManager\n ]);\n\n // No return value needed - hook works internally\n};\n\n// Type definition for event callback - to match ResourceManager's expected type\ntype EventCallback = EventListenerOrEventListenerObject;\n\nexport default useMouseDrag;"],"names":["useRef","useCallback","gsap","useEffect"],"mappings":"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"}