UNPKG

rynex

Version:

A minimalist TypeScript framework for building reactive web applications with no virtual DOM

205 lines 6.22 kB
/** * Rynex Animation & Transition Helpers * Simple, performant animations without external dependencies */ import { debugLog, debugWarn } from '../debug.js'; /** * Transition wrapper - applies CSS transitions to elements * Usage: transition(element, { duration: 300, easing: 'ease-in-out' }) */ export function transition(element, config = {}) { if (!element || !(element instanceof HTMLElement)) { debugWarn('Animation', 'Invalid element provided to transition'); return element; } const { duration = 300, easing = 'ease', delay = 0, onStart, onEnd } = config; try { element.style.transition = `all ${duration}ms ${easing} ${delay}ms`; debugLog('Animation', `Transition applied: ${duration}ms ${easing}`); if (onStart) { onStart(); } if (onEnd) { element.addEventListener('transitionend', () => onEnd(), { once: true }); } } catch (error) { debugWarn('Animation', 'Error applying transition:', error); } return element; } /** * Animate - Web Animations API wrapper * Usage: animate(element, { keyframes: [{ opacity: 0 }, { opacity: 1 }], duration: 300 }) */ export function animate(element, config) { if (!element || !(element instanceof HTMLElement)) { debugWarn('Animation', 'Invalid element provided to animate'); return null; } const { keyframes, duration = 300, easing = 'ease', delay = 0, iterations = 1, direction = 'normal', fill = 'both', onStart, onEnd } = config; try { if (onStart) { onStart(); } const animation = element.animate(keyframes, { duration, easing, delay, iterations, direction, fill }); debugLog('Animation', `Animation started: ${duration}ms`); if (onEnd) { animation.onfinish = () => onEnd(); } return animation; } catch (error) { debugWarn('Animation', 'Error creating animation:', error); return null; } } /** * Fade transition - fade in/out * Usage: fade(element, 'in', { duration: 300 }) */ export function fade(element, direction = 'in', config = {}) { if (!element || !(element instanceof HTMLElement)) { debugWarn('Animation', 'Invalid element provided to fade'); return null; } const { duration = 300, easing = 'ease', delay = 0, onStart, onEnd } = config; const currentOpacity = window.getComputedStyle(element).opacity; let keyframes; if (direction === 'toggle') { direction = parseFloat(currentOpacity) > 0.5 ? 'out' : 'in'; } if (direction === 'in') { keyframes = [ { opacity: 0 }, { opacity: 1 } ]; } else { keyframes = [ { opacity: 1 }, { opacity: 0 } ]; } return animate(element, { keyframes, duration, easing, delay, onStart, onEnd }); } /** * Slide transition - slide in/out * Usage: slide(element, 'down', { duration: 300 }) */ export function slide(element, direction = 'down', config = {}) { if (!element || !(element instanceof HTMLElement)) { debugWarn('Animation', 'Invalid element provided to slide'); return null; } const { duration = 300, easing = 'ease', delay = 0, onStart, onEnd } = config; let keyframes; switch (direction) { case 'up': keyframes = [ { transform: 'translateY(100%)', opacity: 0 }, { transform: 'translateY(0)', opacity: 1 } ]; break; case 'down': keyframes = [ { transform: 'translateY(-100%)', opacity: 0 }, { transform: 'translateY(0)', opacity: 1 } ]; break; case 'left': keyframes = [ { transform: 'translateX(100%)', opacity: 0 }, { transform: 'translateX(0)', opacity: 1 } ]; break; case 'right': keyframes = [ { transform: 'translateX(-100%)', opacity: 0 }, { transform: 'translateX(0)', opacity: 1 } ]; break; } return animate(element, { keyframes, duration, easing, delay, onStart, onEnd }); } /** * Scale transition - scale in/out * Usage: scale(element, 'in', { duration: 300 }) */ export function scale(element, direction = 'in', config = {}) { if (!element || !(element instanceof HTMLElement)) { debugWarn('Animation', 'Invalid element provided to scale'); return null; } const { duration = 300, easing = 'ease', delay = 0, onStart, onEnd } = config; const currentTransform = window.getComputedStyle(element).transform; let keyframes; if (direction === 'toggle') { direction = currentTransform !== 'none' && currentTransform.includes('scale') ? 'out' : 'in'; } if (direction === 'in') { keyframes = [ { transform: 'scale(0)', opacity: 0 }, { transform: 'scale(1)', opacity: 1 } ]; } else { keyframes = [ { transform: 'scale(1)', opacity: 1 }, { transform: 'scale(0)', opacity: 0 } ]; } return animate(element, { keyframes, duration, easing, delay, onStart, onEnd }); } /** * Rotate transition - rotate element * Usage: rotate(element, 360, { duration: 300 }) */ export function rotate(element, degrees = 360, config = {}) { if (!element || !(element instanceof HTMLElement)) { debugWarn('Animation', 'Invalid element provided to rotate'); return null; } const { duration = 300, easing = 'ease', delay = 0, onStart, onEnd } = config; const keyframes = [ { transform: 'rotate(0deg)' }, { transform: `rotate(${degrees}deg)` } ]; return animate(element, { keyframes, duration, easing, delay, onStart, onEnd }); } //# sourceMappingURL=animations.js.map