UNPKG

kinetic-slider

Version:

A WebGL-powered kinetic slider component using PIXI.js

320 lines (317 loc) 10.6 kB
import { useRef, useCallback, useEffect } from 'react'; import { gsap } from 'gsap'; import { RenderScheduler } from '../managers/RenderScheduler.js'; import { UpdateType } from '../managers/UpdateTypes.js'; import { AnimationCoordinator, AnimationGroupType } from '../managers/AnimationCoordinator.js'; const isDevelopment = false; const useIdleTimer = ({ sliderRef, cursorActive, bgDispFilterRef, cursorDispFilterRef, cursorImgEffect, defaultBgFilterScale, defaultCursorFilterScale, idleTimeout = 300, resourceManager }) => { const idleTimerRef = useRef(null); const animationStateRef = useRef({ isAnimating: false, activeAnimations: [], pendingBatchAnimations: [] }); const isUnmountingRef = useRef(false); const lastAnimationOpRef = useRef(0); const animationCoordinator = AnimationCoordinator.getInstance(); useCallback(() => { try { if (isUnmountingRef.current || !resourceManager) return; const { pendingBatchAnimations } = animationStateRef.current; if (pendingBatchAnimations.length > 0) { if (isDevelopment) ; resourceManager.trackAnimationBatch(pendingBatchAnimations); pendingBatchAnimations.length = 0; const now = performance.now(); const opTime = now - lastAnimationOpRef.current; if (isDevelopment && lastAnimationOpRef.current > 0) ; lastAnimationOpRef.current = now; } } catch (error) { animationStateRef.current.pendingBatchAnimations = []; } }, [resourceManager]); useCallback((animation) => { try { if (isUnmountingRef.current) return animation; animationStateRef.current.pendingBatchAnimations.push(animation); return animation; } catch (error) { return animation; } }, []); const createFilterAnimations = useCallback((targetScale, duration = 0.5, onComplete) => { try { if (isUnmountingRef.current) return []; lastAnimationOpRef.current = performance.now(); if (isDevelopment) ; const animations = []; if (bgDispFilterRef.current) { const actualTargetScale = targetScale === 0 ? 0 : defaultBgFilterScale; if (targetScale > 0 && (bgDispFilterRef.current.scale.x === 0 || bgDispFilterRef.current.scale.y === 0)) { bgDispFilterRef.current.scale.x = actualTargetScale; bgDispFilterRef.current.scale.y = actualTargetScale; if (isDevelopment) ; } const bgTween = gsap.to(bgDispFilterRef.current.scale, { x: actualTargetScale, y: actualTargetScale, duration, ease: "power2.out", onComplete: () => { if (resourceManager && bgDispFilterRef.current) { resourceManager.trackFilter(bgDispFilterRef.current); } if (isDevelopment) ; } }); animations.push(bgTween); } if (cursorImgEffect && cursorDispFilterRef.current) { const cursorScale = targetScale === 0 ? 0 : defaultCursorFilterScale; if (targetScale > 0 && (cursorDispFilterRef.current.scale.x === 0 || cursorDispFilterRef.current.scale.y === 0)) { cursorDispFilterRef.current.scale.x = cursorScale; cursorDispFilterRef.current.scale.y = cursorScale; if (isDevelopment) ; } const cursorTween = gsap.to(cursorDispFilterRef.current.scale, { x: cursorScale, y: cursorScale, duration, ease: "power2.out", onComplete: () => { if (resourceManager && cursorDispFilterRef.current) { resourceManager.trackFilter(cursorDispFilterRef.current); } if (isDevelopment) ; } }); animations.push(cursorTween); } const groupType = targetScale === 0 ? AnimationGroupType.IDLE_EFFECT : AnimationGroupType.INTERACTION; animationCoordinator.queueAnimationGroup({ id: `filter_animation_${Date.now()}`, type: groupType, animations, onComplete }); return animations; } catch (error) { if (onComplete) onComplete(); return []; } }, [ bgDispFilterRef, cursorDispFilterRef, cursorImgEffect, defaultCursorFilterScale, defaultBgFilterScale, resourceManager, animationCoordinator ]); const resetFilters = useCallback(() => { try { if (isUnmountingRef.current) return; if (isDevelopment) ; if (idleTimerRef.current !== null) { window.clearTimeout(idleTimerRef.current); idleTimerRef.current = null; } if (cursorActive.current) { if (isDevelopment) ; return; } animationCoordinator.cancelAnimationsByType(AnimationGroupType.IDLE_EFFECT); createFilterAnimations(0, 0.5, () => { if (isDevelopment) ; }); animationCoordinator.scheduleAnimationUpdate( AnimationGroupType.IDLE_EFFECT, () => { if (isDevelopment) ; }, "idle_reset" ); } catch (error) { } }, [ cursorActive, createFilterAnimations, animationCoordinator ]); const restoreFilters = useCallback((immediate = false) => { try { if (isUnmountingRef.current) return; if (isDevelopment) ; if (idleTimerRef.current !== null) { window.clearTimeout(idleTimerRef.current); idleTimerRef.current = null; } animationCoordinator.cancelAnimationsByType(AnimationGroupType.INTERACTION); cursorActive.current = true; if (bgDispFilterRef.current) { const originalX = bgDispFilterRef.current.scale.x; const originalY = bgDispFilterRef.current.scale.y; bgDispFilterRef.current.scale.x = defaultBgFilterScale; bgDispFilterRef.current.scale.y = defaultBgFilterScale; if (isDevelopment) ; } if (cursorImgEffect && cursorDispFilterRef.current) { const originalX = cursorDispFilterRef.current.scale.x; const originalY = cursorDispFilterRef.current.scale.y; cursorDispFilterRef.current.scale.x = defaultCursorFilterScale; cursorDispFilterRef.current.scale.y = defaultCursorFilterScale; if (isDevelopment) ; } RenderScheduler.getInstance().scheduleTypedUpdate( "idleTimer", UpdateType.DISPLACEMENT_EFFECT, () => { if (isDevelopment) ; }, immediate ? "critical" : "high" // Use critical priority for immediate restoration ); const animationDuration = immediate ? 0.2 : 0.5; createFilterAnimations(defaultBgFilterScale, animationDuration, () => { if (isDevelopment) ; }); animationCoordinator.scheduleAnimationUpdate( AnimationGroupType.INTERACTION, () => { if (isDevelopment) ; }, immediate ? "critical" : "high" ); } catch (error) { } }, [ defaultBgFilterScale, defaultCursorFilterScale, bgDispFilterRef, cursorDispFilterRef, cursorImgEffect, cursorActive, createFilterAnimations, animationCoordinator ]); const handleMouseMove = useCallback(() => { try { if (isUnmountingRef.current) return; if (idleTimerRef.current !== null) { window.clearTimeout(idleTimerRef.current); idleTimerRef.current = null; } if (cursorActive.current !== true) { cursorActive.current = true; if (isDevelopment) ; const bgFilter2 = bgDispFilterRef.current; const cursorFilter2 = cursorDispFilterRef.current; if (bgFilter2) { bgFilter2.scale.x = defaultBgFilterScale; bgFilter2.scale.y = defaultBgFilterScale; if (isDevelopment) ; } if (cursorImgEffect && cursorFilter2) { cursorFilter2.scale.x = defaultCursorFilterScale; cursorFilter2.scale.y = defaultCursorFilterScale; if (isDevelopment) ; } RenderScheduler.getInstance().scheduleTypedUpdate( "idleTimer", UpdateType.DISPLACEMENT_EFFECT, () => { if (isDevelopment) ; }, "critical" // Use critical priority to ensure immediate processing ); restoreFilters(true); } const bgFilter = bgDispFilterRef.current; const cursorFilter = cursorDispFilterRef.current; const bgFilterInactive = bgFilter && (bgFilter.scale.x === 0 || bgFilter.scale.y === 0); const cursorFilterInactive = cursorImgEffect && cursorFilter && (cursorFilter.scale.x === 0 || cursorFilter.scale.y === 0); if (bgFilterInactive || cursorFilterInactive) { if (isDevelopment) ; restoreFilters(true); } idleTimerRef.current = window.setTimeout(() => { cursorActive.current = false; if (isDevelopment) ; resetFilters(); idleTimerRef.current = null; }, idleTimeout); } catch (error) { } }, [ cursorActive, bgDispFilterRef, cursorDispFilterRef, cursorImgEffect, defaultBgFilterScale, defaultCursorFilterScale, idleTimeout, resetFilters, restoreFilters ]); useEffect(() => { if (typeof window === "undefined") return; if (!sliderRef.current) return; isUnmountingRef.current = false; try { const node = sliderRef.current; if (resourceManager) { const listeners = /* @__PURE__ */ new Map(); listeners.set("mousemove", [handleMouseMove]); resourceManager.addEventListenerBatch(node, listeners); } else { node.addEventListener("mousemove", handleMouseMove, { passive: true }); } idleTimerRef.current = window.setTimeout(() => { cursorActive.current = false; resetFilters(); idleTimerRef.current = null; }, idleTimeout); return () => { isUnmountingRef.current = true; try { if (idleTimerRef.current !== null) { window.clearTimeout(idleTimerRef.current); idleTimerRef.current = null; } if (!resourceManager) { node.removeEventListener("mousemove", handleMouseMove); } } catch (cleanupError) { if (isDevelopment) ; } }; } catch (error) { return () => { }; } }, [ sliderRef, handleMouseMove, idleTimeout, resetFilters, resourceManager ]); return { resetFilters, restoreFilters }; }; export { useIdleTimer as default }; //# sourceMappingURL=useIdleTimer.js.map