// modules/sticky-fade/index.js import { registerFrameTask, unregisterFrameTask } from '../../core/frameloop.js'; let taskId = 'sticky-fade'; let elements = []; let lastScrollY = window.scrollY; let activeMap = new WeakMap(); let configCache = { direction: false, reset: false, }; export function init(config = {}) { elements = Array.from(document.querySelectorAll('[data-sticky-fade]')); if (elements.length === 0) return; configCache.direction = config.direction ?? false; configCache.reset = config.reset ?? false; registerFrameTask(taskId, () => { const scrollY = window.scrollY; const direction = scrollY > lastScrollY ? 'down' : scrollY < lastScrollY ? 'up' : 'none'; lastScrollY = scrollY; const viewportHeight = window.innerHeight; elements.forEach(el => { const rect = el.getBoundingClientRect(); const progress = 1 - Math.min(Math.max(rect.top / viewportHeight, 0), 1); el.style.opacity = progress.toFixed(3); el.style.transform = `translateY(${(1 - progress) * 20}px)`; if(configCache.direction) { el.dataset.scrollDir = direction; } if (configCache.reset) { const isVisible = progress >= 1; const wasActive = activeMap.get(el) || false; if(isVisible && !wasActive) { el.classList.add('visible'); activeMap.set(el, true); } else if(!isVisible && wasActive) { el.classList.remove('visible'); activeMap.set(el, false); } } }); }, { autoStart: true }); } export function destroy() { unregisterFrameTask(taskId); elements.forEach(el => { el.style.opacity = ''; el.style.transform = ''; el.classList.remove('visible'); delete el.dataset.scrollDir; }); elements = []; activeMap = new WeakMap(); }