kinetic-slider
Version:
A WebGL-powered kinetic slider component using PIXI.js
1 lines • 53.5 kB
Source Map (JSON)
{"version":3,"file":"useFilters.cjs","sources":["../../../src/hooks/useFilters.ts"],"sourcesContent":["import { useEffect, useRef, useCallback } from 'react';\nimport { Container, Sprite, Filter, AlphaFilter } from 'pixi.js';\nimport { type FilterConfig, type FilterType, type BaseFilterConfig } from '../filters/types';\nimport { FilterFactory } from '../filters';\nimport {\n type HookParams,\n type FilterBatchConfig,\n type FilterDiff\n} from '../types';\nimport ResourceManager from '../managers/ResourceManager';\nimport { type FilterResult } from '../filters';\nimport RenderScheduler from '../managers/RenderScheduler';\nimport { createHookUpdateHelper, UpdateType } from '../managers/UpdateTypes';\nimport gsap from 'gsap';\n\n// Development environment check\nconst isDevelopment = typeof import.meta.env !== 'undefined' && import.meta.env.DEV !== undefined\n ? import.meta.env.DEV\n : process.env.NODE_ENV === 'development';\n\n// Define the custom event name for filter coordination\nconst FILTER_COORDINATION_EVENT = 'kinetic-slider:filter-update';\n\n// Interface for filter update event detail\ninterface FilterUpdateEventDetail {\n type: string;\n intensity: number;\n timestamp?: number;\n source?: string;\n priority?: UpdatePriority;\n}\n\n// Define a more specific type for the target objects we're applying filters to\ntype FilterableObject = Sprite | Container;\n\n// Type to represent a map of objects to their applied filters and control functions\ninterface FilterMap {\n [id: string]: {\n target: FilterableObject;\n filters: {\n instance: Filter;\n updateIntensity: (intensity: number) => void;\n reset: () => void;\n initialIntensity: number;\n }[];\n };\n}\n\n// Type for storing original filter configurations\ninterface OriginalFilterConfigs {\n image: FilterConfig[];\n text: FilterConfig[];\n}\n\n// Type to represent update priority\ntype UpdatePriority = 'high' | 'normal' | 'low' | 'critical';\n\n// Enhanced filter update type for batch processing\ninterface BatchFilterUpdate {\n filterId: string;\n changes: Partial<BaseFilterConfig>;\n timestamp: number;\n priority: UpdatePriority;\n}\n\n// Interface for the hook's return value\ninterface UseFiltersResult {\n updateFilterIntensities: (active: boolean, forceUpdate?: boolean) => void;\n resetAllFilters: () => void;\n activateFilterEffects: () => void;\n isInitialized: boolean;\n isActive: boolean;\n setFiltersActive: (active: boolean) => void;\n}\n\nexport const useFilters = (\n { pixi, props, resourceManager }:\n Omit<HookParams, 'sliderRef'> & { resourceManager?: ResourceManager | null }\n): UseFiltersResult => {\n if (isDevelopment) {\n console.log('[useFilters] Hook called with:', {\n hasApp: !!pixi.app.current,\n hasStage: !!(pixi.app.current?.stage),\n slidesCount: pixi.slides.current?.length,\n textContainersCount: pixi.textContainers.current?.length,\n hasResourceManager: !!resourceManager,\n imageFilters: props.imageFilters,\n textFilters: props.textFilters\n });\n }\n\n // Move all the useRef calls here\n const filterMapRef = useRef<FilterMap>({});\n // Store original filter configurations separately\n const originalConfigsRef = useRef<OriginalFilterConfigs>({ image: [], text: [] });\n const filtersInitializedRef = useRef<boolean>(false);\n const filtersActiveRef = useRef<boolean>(false);\n const debouncedRenderRef = useRef<number | null>(null);\n const isMountedRef = useRef<boolean>(true);\n\n // Add refs for our filter application functions to avoid circular references\n const applyFiltersToTargetRef = useRef<(target: FilterableObject, configs: FilterConfig[], id: string) => Promise<void>>(null!);\n const applyFiltersToObjectsRef = useRef<(targets: FilterableObject[], configs: FilterConfig[], baseId: string) => Promise<void>>(null!);\n\n // Store batch resource collections for efficient management\n const batchCollectionRef = useRef<{\n pendingFilters: Filter[];\n pendingObjects: FilterableObject[];\n }>({\n pendingFilters: [],\n pendingObjects: []\n });\n\n // Batch update queue and configuration\n const batchQueueRef = useRef<BatchFilterUpdate[]>([]);\n const batchConfigRef = useRef<FilterBatchConfig>({\n bufferMs: 16, // One frame at 60fps - will be adjusted dynamically\n maxBatchSize: 10 // Will be adjusted dynamically\n });\n const batchTimeoutRef = useRef<number | null>(null);\n\n // Performance metrics tracking\n const performanceMetricsRef = useRef<{\n lastProcessTime: number;\n averageProcessTime: number;\n updateCount: number;\n bufferAdjustmentCounter: number;\n totalProcessTime: number;\n }>({\n lastProcessTime: 0,\n averageProcessTime: 0,\n updateCount: 0,\n bufferAdjustmentCounter: 0,\n totalProcessTime: 0\n });\n\n // Add a cache for filter states to avoid redundant calculations\n const filterStateCache = useRef<Map<string, any>>(new Map());\n\n // Create a ref to hold the processBatchQueue function\n const processBatchQueueRef = useRef<() => void>(() => {\n const start = performance.now();\n const queue = [...batchQueueRef.current];\n\n // Clear the queue before processing to avoid duplicates if called twice\n batchQueueRef.current = [];\n\n if (queue.length === 0) return;\n\n if (isDevelopment) {\n console.log(`[useFilters] Processing batch of ${queue.length} filter updates`);\n }\n\n // Group updates by filterId to apply only the latest update for each filter\n const updates: Record<string, BatchFilterUpdate> = {};\n\n // Define priority order mapping for sorting\n const priorityOrder: Record<UpdatePriority, number> = {\n 'low': 0,\n 'normal': 1,\n 'high': 2,\n 'critical': 3\n };\n\n // Process updates from lowest to highest priority\n queue.sort((a, b) => {\n return priorityOrder[a.priority] - priorityOrder[b.priority];\n });\n\n // Keep only the latest update for each filter, prioritizing higher priority\n for (const update of queue) {\n // If we already have an update for this filter with higher or equal priority, skip\n if (updates[update.filterId] &&\n priorityOrder[updates[update.filterId].priority] >= priorityOrder[update.priority]) {\n continue;\n }\n\n // Otherwise, keep this update\n updates[update.filterId] = update;\n }\n\n // Apply all updates\n Object.values(updates).forEach(update => {\n const { filterId, changes } = update;\n const [targetId, filterIndex] = filterId.split('-');\n\n if (!filterMapRef.current[targetId]) {\n if (isDevelopment) {\n console.warn(`[useFilters] Filter target not found: ${targetId}`);\n }\n return;\n }\n\n const filterData = filterMapRef.current[targetId].filters[Number(filterIndex)];\n if (!filterData) {\n if (isDevelopment) {\n console.warn(`[useFilters] Filter not found: ${filterId}`);\n }\n return;\n }\n\n // Apply intensity change if specified\n if (changes.intensity !== undefined) {\n filterData.updateIntensity(changes.intensity);\n if (isDevelopment) {\n console.log(`[useFilters] Set filter ${filterId} to ${changes.enabled ? 'active' : 'inactive'} with intensity ${changes.intensity}`);\n }\n }\n\n // Apply enabled state if specified\n if (changes.enabled !== undefined) {\n filterData.instance.enabled = changes.enabled;\n }\n });\n\n // Calculate processing time and update metrics\n const end = performance.now();\n const processingTime = end - start;\n\n const metrics = performanceMetricsRef.current;\n metrics.lastProcessTime = processingTime;\n metrics.totalProcessTime += processingTime;\n metrics.updateCount += queue.length;\n metrics.averageProcessTime = metrics.totalProcessTime / metrics.updateCount;\n\n // Dynamically adjust buffer size based on performance\n metrics.bufferAdjustmentCounter++;\n if (metrics.bufferAdjustmentCounter >= 10) {\n metrics.bufferAdjustmentCounter = 0;\n\n // If processing is taking too long, increase buffer time\n if (metrics.averageProcessTime > 4) { // 4ms is 25% of a 60fps frame\n batchConfigRef.current.bufferMs = Math.min(50, batchConfigRef.current.bufferMs + 4);\n if (isDevelopment) {\n console.log(`[useFilters] Increased batch buffer to ${batchConfigRef.current.bufferMs}ms due to slow processing`);\n }\n } else if (metrics.averageProcessTime < 2 && batchConfigRef.current.bufferMs > 16) {\n // If processing is fast, decrease buffer time, but not below 16ms\n batchConfigRef.current.bufferMs = Math.max(16, batchConfigRef.current.bufferMs - 2);\n if (isDevelopment) {\n console.log(`[useFilters] Decreased batch buffer to ${batchConfigRef.current.bufferMs}ms due to fast processing`);\n }\n }\n }\n\n // Trigger a render update via the Pixi app ticker if available\n if (pixi.app.current) {\n pixi.app.current.render();\n }\n });\n\n // Create a ref to hold the scheduleNextBatch function\n const scheduleNextBatchRef = useRef<() => void>(() => {\n // Clear any existing timeout\n if (batchTimeoutRef.current !== null) {\n window.clearTimeout(batchTimeoutRef.current);\n batchTimeoutRef.current = null;\n }\n\n // If there are updates in the queue, schedule processing\n if (batchQueueRef.current.length > 0) {\n // If we have critical updates, process immediately\n if (batchQueueRef.current.some(update => update.priority === 'critical')) {\n processBatchQueueRef.current();\n return;\n }\n\n // If we have high priority updates and enough of them, process sooner\n const highPriorityCount = batchQueueRef.current.filter(update =>\n update.priority === 'high').length;\n\n if (highPriorityCount > 0 && (\n highPriorityCount >= 3 ||\n batchQueueRef.current.length >= batchConfigRef.current.maxBatchSize\n )) {\n processBatchQueueRef.current();\n return;\n }\n\n // Otherwise, schedule processing after buffer time\n batchTimeoutRef.current = window.setTimeout(() => {\n processBatchQueueRef.current();\n batchTimeoutRef.current = null;\n }, batchConfigRef.current.bufferMs);\n }\n });\n\n /**\n * Process filter configurations to normalize them\n *\n * @param filterConfig - Single filter config or array of configs\n * @returns Array of normalized filter configs\n */\n const processFilterConfigs = (filterConfig?: any): FilterConfig[] => {\n if (!filterConfig) {\n return [];\n }\n\n // Normalize to array\n const configs = Array.isArray(filterConfig) ? filterConfig : [filterConfig];\n\n // Filter out invalid configs and ensure required properties\n return configs.filter(config => {\n // Must have a type property\n if (!config || !config.type) {\n if (isDevelopment) {\n console.warn('Invalid filter config - missing type:', config);\n }\n return false;\n }\n\n return true;\n }).map(config => {\n // Create a new object without duplicating properties\n return {\n type: config.type,\n // Set default values only if not defined in config\n enabled: config.enabled ?? true, // Default to enabled if not explicitly disabled\n intensity: config.intensity ?? 1, // Default intensity 1 if not defined\n ...config // Keep all other properties from config (might override defaults)\n };\n });\n };\n\n // Add a helper function for type conversion\n const adaptFilterConfig = (config: any): FilterConfig => {\n const { type, enabled = true, intensity = 1, options = {}, ...rest } = config;\n\n // Merge options with other properties\n const filterProperties = { ...rest, ...options };\n\n return {\n type: type as FilterType,\n enabled: enabled !== false,\n intensity: intensity || 1,\n ...filterProperties\n } as FilterConfig;\n };\n\n /**\n * Apply filters to a collection of target objects\n */\n const applyFiltersToObjects = useCallback(async (\n targets: FilterableObject[],\n configs: FilterConfig[],\n baseId: string\n ): Promise<void> => {\n // Skip if no configs or targets provided\n if (!configs || configs.length === 0 || !targets || targets.length === 0) {\n if (isDevelopment) {\n console.log(`No filter configs or targets provided for ${baseId}`);\n }\n return;\n }\n\n // Safeguard against missing ref\n if (!applyFiltersToTargetRef.current) {\n console.error('[useFilters] applyFiltersToTargetRef.current is not defined');\n return;\n }\n\n // Convert the configs if necessary\n const processedConfigs = configs.map(c => adaptFilterConfig(c));\n\n // Process each target\n const applyPromises = targets.map((target, index) => {\n const targetId = `${baseId}-${index}`;\n return applyFiltersToTargetRef.current!(target, processedConfigs, targetId);\n });\n\n // Wait for all filters to be applied\n await Promise.all(applyPromises);\n }, []);\n\n // Store the function in the ref\n useEffect(() => {\n applyFiltersToObjectsRef.current = applyFiltersToObjects;\n }, [applyFiltersToObjects]);\n\n /**\n * Updates the intensity of all filters\n * @param active Whether the filters should be active or inactive\n * @param force Whether to force update all filters\n */\n const updateFilterIntensities = useCallback((active: boolean, force: boolean = false) => {\n if (!filtersInitializedRef.current) {\n if (isDevelopment) {\n console.log('[useFilters] Filters not initialized, skipping intensity update');\n }\n return;\n }\n\n if (isDevelopment) {\n console.log(`[useFilters] Setting filter intensity to ${active ? 'active' : 'inactive'}`);\n }\n\n // Create a batch of updates\n const batchUpdates: BatchFilterUpdate[] = [];\n\n // For each filter, set its enabled state and set appropriate intensity\n Object.entries(filterMapRef.current).forEach(([targetId, filterData]) => {\n try {\n // Add type assertion\n const typedFilterData = filterData as {\n target: FilterableObject;\n filters: {\n instance: Filter;\n updateIntensity: (intensity: number) => void;\n reset: () => void;\n initialIntensity: number;\n }[];\n };\n\n if (!typedFilterData.target) return;\n\n const { target, filters } = typedFilterData;\n\n if (!target || !filters || filters.length === 0) return;\n\n // Skip if filter is already in the desired state and not forcing\n if (!force && filters.some(f => f.instance.enabled === active)) return;\n\n // Directly update the filter\n filters.forEach(f => {\n f.instance.enabled = active;\n if (active) {\n // Set intensity based on config\n if (f.initialIntensity !== undefined) {\n f.updateIntensity(f.initialIntensity);\n }\n } else {\n // Set to zero intensity\n f.updateIntensity(0);\n }\n });\n\n if (isDevelopment) {\n console.log(`[useFilters] Set filter ${targetId} to ${active ? 'active' : 'inactive'} with intensity ${active ? 'initial' : 0}`);\n }\n\n // Add to batch\n batchUpdates.push({\n filterId: targetId,\n changes: {\n enabled: active\n },\n timestamp: performance.now(),\n priority: force ? 'critical' : 'normal'\n });\n } catch (error) {\n if (isDevelopment) {\n console.error(`[useFilters] Error updating filter ${targetId}:`, error);\n }\n }\n });\n\n // Process the batch\n if (batchUpdates.length > 0) {\n if (isDevelopment) {\n console.log(`[useFilters] Processing batch of ${batchUpdates.length} filter updates`);\n }\n batchQueueRef.current.push(...batchUpdates);\n\n // If force is true, process immediately\n if (force) {\n processBatchQueueRef.current();\n } else {\n // Otherwise schedule processing\n scheduleNextBatchRef.current();\n }\n }\n\n // Update active state\n filtersActiveRef.current = active;\n }, [filtersInitializedRef.current]);\n\n /**\n * Reset all filters to their default state\n */\n const resetAllFilters = useCallback(() => {\n if (!filtersInitializedRef.current) {\n if (isDevelopment) {\n console.log('[useFilters] Filters not initialized, skipping reset');\n }\n return;\n }\n\n if (isDevelopment) {\n console.log('[useFilters] Resetting all filters to default state');\n }\n\n // Prepare batch updates\n const updates: BatchFilterUpdate[] = [];\n const now = performance.now();\n\n // Queue reset operations for all filters\n Object.entries(filterMapRef.current).forEach(([targetId, filterData]) => {\n const typedFilterData = filterData as {\n target: FilterableObject;\n filters: {\n instance: Filter;\n updateIntensity: (intensity: number) => void;\n reset: () => void;\n initialIntensity: number;\n }[];\n };\n\n typedFilterData.filters.forEach((filter, index) => {\n const filterId = `${targetId}-${index}`;\n\n // Add reset operation to batch queue\n updates.push({\n filterId,\n changes: {\n intensity: filter.initialIntensity,\n enabled: true\n },\n timestamp: now,\n priority: 'normal'\n });\n\n if (isDevelopment) {\n console.log(`[useFilters] Reset filter ${filterId} to default state`);\n }\n });\n });\n\n // Add updates to the batch queue\n batchQueueRef.current.push(...updates);\n\n // Schedule processing\n scheduleNextBatchRef.current();\n\n // Call the reset function on each filter outside the batch\n // This is done separately since reset operations might involve complex state resets\n // that aren't handled by simple property changes\n Object.entries(filterMapRef.current).forEach(([_, filterData]) => {\n const typedFilterData = filterData as {\n target: FilterableObject;\n filters: {\n instance: Filter;\n updateIntensity: (intensity: number) => void;\n reset: () => void;\n initialIntensity: number;\n }[];\n };\n\n typedFilterData.filters.forEach(filter => {\n filter.reset();\n });\n });\n }, []);\n\n /**\n * Activate filter effects\n */\n const activateFilterEffects = useCallback(() => {\n try {\n // If filters are already initialized, just update their intensity\n if (filtersInitializedRef.current) {\n updateFilterIntensities(true, true);\n return;\n }\n\n if (isDevelopment) {\n console.log('[useFilters] Filters not initialized, initializing now before activation');\n }\n\n // Check if we have the required objects to initialize filters\n if (!pixi.app.current || !pixi.slides.current || !pixi.slides.current.length) {\n console.log('[useFilters] Missing required objects for filter initialization');\n return;\n }\n\n // Process filter configs\n const imageFilterConfigs = processFilterConfigs(props.imageFilters || []);\n const textFilterConfigs = processFilterConfigs(props.textFilters || []);\n\n // Store original configs\n originalConfigsRef.current = {\n image: [...imageFilterConfigs],\n text: [...textFilterConfigs]\n };\n\n console.log(`[useFilters] Initializing filters: ${imageFilterConfigs.length} image filters, ${textFilterConfigs.length} text filters`);\n\n // Apply filters to slides\n if (pixi.slides.current && pixi.slides.current.length) {\n pixi.slides.current.forEach((slide, index) => {\n if (!slide) return;\n\n const slideName = `slide-${index}`;\n console.log(`[useFilters] Creating filters for ${slideName}`);\n\n // Create the filter entry\n filterMapRef.current[slideName] = {\n target: slide,\n filters: []\n };\n\n // Apply each filter\n imageFilterConfigs.forEach(async (config, filterIndex) => {\n try {\n // Create the filter via FilterFactory\n const filterResult = await FilterFactory.createFilterAsync(config as any);\n const filter = filterResult.filter;\n filter.enabled = true;\n\n // Add the filter to the slide\n if (!slide.filters) {\n slide.filters = [filter];\n } else if (Array.isArray(slide.filters)) {\n slide.filters.push(filter);\n }\n\n // Store the filter data\n filterMapRef.current[slideName].filters.push({\n instance: filter,\n updateIntensity: (intensity) => {\n console.log(`[useFilters] Updated ${slideName} filter ${filterIndex} intensity to ${intensity}`);\n filterResult.updateIntensity(intensity);\n },\n reset: () => {\n console.log(`[useFilters] Reset ${slideName} filter ${filterIndex}`);\n filterResult.reset();\n },\n initialIntensity: config.intensity || 1\n });\n\n console.log(`[useFilters] Created filter for ${slideName} with type ${config.type}`);\n } catch (err) {\n console.error(`[useFilters] Error creating filter for ${slideName}:`, err);\n }\n });\n });\n }\n\n // Apply filters to text containers\n if (pixi.textContainers.current && pixi.textContainers.current.length) {\n pixi.textContainers.current.forEach((container, index) => {\n if (!container) return;\n\n const containerName = `text-container-${index}`;\n console.log(`[useFilters] Creating filters for ${containerName}`);\n\n // Create the filter entry\n filterMapRef.current[containerName] = {\n target: container,\n filters: []\n };\n\n // Apply each filter\n textFilterConfigs.forEach(async (config, filterIndex) => {\n try {\n // Create the filter via FilterFactory\n const filterResult = await FilterFactory.createFilterAsync(config as any);\n const filter = filterResult.filter;\n filter.enabled = true;\n\n // Add the filter to the container\n if (!container.filters) {\n container.filters = [filter];\n } else if (Array.isArray(container.filters)) {\n container.filters.push(filter);\n }\n\n // Store the filter data\n filterMapRef.current[containerName].filters.push({\n instance: filter,\n updateIntensity: (intensity) => {\n console.log(`[useFilters] Updated ${containerName} filter ${filterIndex} intensity to ${intensity}`);\n filterResult.updateIntensity(intensity);\n },\n reset: () => {\n console.log(`[useFilters] Reset ${containerName} filter ${filterIndex}`);\n filterResult.reset();\n },\n initialIntensity: config.intensity || 1\n });\n\n console.log(`[useFilters] Created filter for ${containerName} with type ${config.type}`);\n } catch (err) {\n console.error(`[useFilters] Error creating filter for ${containerName}:`, err);\n }\n });\n });\n }\n\n // Mark filters as initialized\n filtersInitializedRef.current = true;\n filtersActiveRef.current = true;\n\n console.log('[useFilters] Filters initialized and activated');\n } catch (error) {\n if (isDevelopment) {\n console.error('Error activating filter effects:', error);\n }\n }\n }, [pixi.app, pixi.slides, pixi.textContainers, props.imageFilters, props.textFilters, updateFilterIntensities]);\n\n // Handle filter coordination events from other components\n const handleFilterCoordinationEvent = useCallback((event: Event) => {\n // Implementation of the handleFilterCoordinationEvent function\n console.log('[useFilters] Event handler implemented');\n }, []);\n\n // Set up event listeners for filter coordination\n useEffect(() => {\n // Implementation of the useEffect for setting up event listeners\n window.addEventListener(FILTER_COORDINATION_EVENT, handleFilterCoordinationEvent);\n\n return () => {\n window.removeEventListener(FILTER_COORDINATION_EVENT, handleFilterCoordinationEvent);\n };\n }, [handleFilterCoordinationEvent]);\n\n // Initialize a dummy implementation for applyFiltersToTarget\n // This will be replaced with the real implementation after initialization\n applyFiltersToTargetRef.current = async (target, configs, id) => {\n console.warn(`[useFilters] Dummy applyFiltersToTarget called for ${id} - real implementation not yet available`);\n return Promise.resolve();\n };\n\n // Initialize the RenderScheduler integration\n useEffect(() => {\n const scheduler = RenderScheduler.getInstance();\n const updateHelper = createHookUpdateHelper('useFilters');\n\n // Process batch queue when requested by RenderScheduler\n const scheduledProcessBatch = () => {\n processBatchQueueRef.current();\n };\n\n // Schedule batch processing with the central scheduler\n const scheduleBatchProcessing = () => {\n scheduler.scheduleTypedUpdate(\n 'useFilters',\n UpdateType.FILTER_UPDATE,\n scheduledProcessBatch\n );\n };\n\n // Override scheduleNextBatch to use the RenderScheduler for more coordinated updates\n scheduleNextBatchRef.current = () => {\n // For critical updates, use setTimeout for immediate processing\n if (batchQueueRef.current.some(update => update.priority === 'critical')) {\n if (batchTimeoutRef.current !== null) {\n window.clearTimeout(batchTimeoutRef.current);\n batchTimeoutRef.current = null;\n }\n\n batchTimeoutRef.current = window.setTimeout(() => {\n processBatchQueueRef.current();\n batchTimeoutRef.current = null;\n }, 0);\n return;\n }\n\n // For high priority, schedule sooner but still coordinate with RenderScheduler\n if (batchQueueRef.current.some(update => update.priority === 'high')) {\n scheduleBatchProcessing();\n return;\n }\n\n // For normal/low priority, debounce and batch with a delay\n if (batchTimeoutRef.current !== null) {\n window.clearTimeout(batchTimeoutRef.current);\n batchTimeoutRef.current = null;\n }\n\n batchTimeoutRef.current = window.setTimeout(() => {\n scheduleBatchProcessing();\n batchTimeoutRef.current = null;\n }, batchConfigRef.current.bufferMs);\n };\n\n return () => {\n // Clean up any pending timeouts\n if (batchTimeoutRef.current !== null) {\n window.clearTimeout(batchTimeoutRef.current);\n batchTimeoutRef.current = null;\n }\n\n // Cancel any scheduled updates\n scheduler.cancelTypedUpdate('useFilters', UpdateType.FILTER_UPDATE);\n };\n }, []);\n\n // Clean up resources on unmount\n useEffect(() => {\n return () => {\n // Clear any pending batch operations\n batchQueueRef.current = [];\n\n // Clear any pending timeouts\n if (batchTimeoutRef.current !== null) {\n window.clearTimeout(batchTimeoutRef.current);\n batchTimeoutRef.current = null;\n }\n\n // Reset all filters if they exist\n if (filtersInitializedRef.current) {\n Object.entries(filterMapRef.current).forEach(([_, filterData]) => {\n const typedFilterData = filterData as {\n target: FilterableObject;\n filters: {\n instance: Filter;\n updateIntensity: (intensity: number) => void;\n reset: () => void;\n initialIntensity: number;\n }[];\n };\n\n typedFilterData.filters.forEach(filter => {\n try {\n // Disable the filter\n filter.instance.enabled = false;\n\n // Reset to default state\n filter.reset();\n } catch (err) {\n if (isDevelopment) {\n console.error('[useFilters] Error cleaning up filter:', err);\n }\n }\n });\n });\n }\n };\n }, []);\n\n // Add an event listener to handle mouse leave events from other components\n useEffect(() => {\n if (typeof window === 'undefined') return;\n\n // Handler for filter coordination events from other hooks\n const handleFilterCoordinationEvent = (event: Event) => {\n const customEvent = event as CustomEvent<FilterUpdateEventDetail>;\n const { type, intensity, priority } = customEvent.detail;\n\n if (isDevelopment) {\n console.log(`[useFilters] Received filter coordination event: ${type} = ${intensity}`);\n }\n\n // Only respond to background-displacement and cursor-displacement events\n if (type === 'background-displacement' || type === 'cursor-displacement') {\n if (intensity === 0) {\n // Mouse has left the canvas, deactivate filters\n updateFilterIntensities(false, priority === 'critical');\n } else {\n // Mouse is on the canvas, activate filters\n updateFilterIntensities(true, priority === 'critical');\n }\n }\n };\n\n // Listen for filter coordination events\n window.addEventListener(FILTER_COORDINATION_EVENT, handleFilterCoordinationEvent);\n\n return () => {\n window.removeEventListener(FILTER_COORDINATION_EVENT, handleFilterCoordinationEvent);\n };\n }, [updateFilterIntensities]);\n\n return {\n updateFilterIntensities,\n resetAllFilters,\n activateFilterEffects,\n isInitialized: filtersInitializedRef.current,\n isActive: filtersActiveRef.current,\n setFiltersActive: (active: boolean) => {\n filtersActiveRef.current = active;\n }\n };\n};"],"names":["useRef","useCallback","useEffect","FilterFactory","RenderScheduler","UpdateType","handleFilterCoordinationEvent"],"mappings":"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