{"version":3,"file":"AnimationUtils.mjs","sources":["../src/AnimationUtils.ts"],"sourcesContent":["/**\n * @module AnimationUtils\n * @description A collection of utility functions for handling animations in web applications.\n * Provides methods for CSS transitions, requestAnimationFrame animations, keyframe animations,\n * and spring physics-based animations.\n *\n * @example\n * ```typescript\n * import { AnimationUtils } from 'houser-js-utils';\n *\n * // Animate an element using CSS transitions\n * const element = document.querySelector('.box');\n * await AnimationUtils.animate(element, {\n *   transform: 'translateX(100px)',\n *   opacity: '0.5'\n * });\n *\n * // Create a spring animation\n * await AnimationUtils.createSpringAnimation(element, {\n *   transform: 'translateY(200px)'\n * }, {\n *   stiffness: 170,\n *   damping: 26\n * });\n * ```\n */\n\n/**\n * Spring animation configuration options\n */\ninterface SpringOptions {\n  /** Spring stiffness coefficient (default: 170) */\n  stiffness?: number;\n  /** Damping coefficient (default: 26) */\n  damping?: number;\n  /** Mass of the animated object (default: 1) */\n  mass?: number;\n  /** Maximum duration of the animation in milliseconds (default: 300) */\n  duration?: number;\n}\n\nexport const AnimationUtils = {\n  /**\n   * Animates an element using CSS transitions\n   * @param element - The HTML element to animate\n   * @param properties - CSS properties to animate\n   * @param duration - Animation duration in milliseconds (default: 300)\n   * @param easing - CSS easing function (default: 'ease')\n   * @returns Promise that resolves when animation completes\n   * @example\n   * ```typescript\n   * const element = document.querySelector('.box');\n   * await AnimationUtils.animate(element, {\n   *   transform: 'translateX(100px)',\n   *   opacity: '0.5'\n   * }, 500, 'ease-in-out');\n   * ```\n   */\n  animate(\n    element: HTMLElement,\n    properties: Partial<CSSStyleDeclaration>,\n    duration = 300,\n    easing = \"ease\"\n  ): Promise<void> {\n    return new Promise((resolve) => {\n      const startValues: { [key: string]: number } = {};\n      const endValues: { [key: string]: number } = {};\n\n      // Get start values\n      Object.keys(properties).forEach((key) => {\n        const value = properties[key as keyof CSSStyleDeclaration];\n        if (value !== undefined) {\n          const startValue = parseFloat(\n            getComputedStyle(element)[\n              key as keyof CSSStyleDeclaration\n            ] as string\n          );\n          const endValue = parseFloat(value as string);\n          if (!isNaN(startValue) && !isNaN(endValue)) {\n            startValues[key] = startValue;\n            endValues[key] = endValue;\n          }\n        }\n      });\n\n      // Set initial transition\n      element.style.transition = `all ${duration}ms ${easing}`;\n\n      // Set end values\n      Object.keys(properties).forEach((key) => {\n        const value = properties[key as keyof CSSStyleDeclaration];\n        if (value !== undefined) {\n          (element.style as any)[key] = value;\n        }\n      });\n\n      // Handle animation end\n      const handleTransitionEnd = () => {\n        element.removeEventListener(\"transitionend\", handleTransitionEnd);\n        element.style.transition = \"\";\n        resolve();\n      };\n\n      element.addEventListener(\"transitionend\", handleTransitionEnd);\n\n      // Fallback timeout\n      setTimeout(handleTransitionEnd, duration);\n    });\n  },\n\n  /**\n   * Animates an element using requestAnimationFrame for smoother animations\n   * @param element - The HTML element to animate\n   * @param properties - CSS properties to animate\n   * @param duration - Animation duration in milliseconds (default: 300)\n   * @param easing - Custom easing function (default: linear)\n   * @returns Promise that resolves when animation completes\n   * @example\n   * ```typescript\n   * const element = document.querySelector('.box');\n   * await AnimationUtils.animateWithRAF(element, {\n   *   transform: 'translateX(100px)'\n   * }, 500, (t) => t * t); // Quadratic easing\n   * ```\n   */\n  animateWithRAF(\n    element: HTMLElement,\n    properties: Partial<CSSStyleDeclaration>,\n    duration = 300,\n    easing = (t: number) => t\n  ): Promise<void> {\n    return new Promise((resolve) => {\n      const startTime = performance.now();\n      const startValues: { [key: string]: number } = {};\n      const endValues: { [key: string]: number } = {};\n\n      // Get start values\n      Object.keys(properties).forEach((key) => {\n        const value = properties[key as keyof CSSStyleDeclaration];\n        if (value !== undefined) {\n          const startValue = parseFloat(\n            getComputedStyle(element)[\n              key as keyof CSSStyleDeclaration\n            ] as string\n          );\n          const endValue = parseFloat(value as string);\n          if (!isNaN(startValue) && !isNaN(endValue)) {\n            startValues[key] = startValue;\n            endValues[key] = endValue;\n          }\n        }\n      });\n\n      const animate = (currentTime: number) => {\n        const elapsed = currentTime - startTime;\n        const progress = Math.min(elapsed / duration, 1);\n        const easedProgress = easing(progress);\n\n        Object.keys(startValues).forEach((key) => {\n          const startValue = startValues[key];\n          const endValue = endValues[key];\n          const currentValue =\n            startValue + (endValue - startValue) * easedProgress;\n          (element.style as any)[key] = `${currentValue}px`;\n        });\n\n        if (progress < 1) {\n          requestAnimationFrame(animate);\n        } else {\n          resolve();\n        }\n      };\n\n      requestAnimationFrame(animate);\n    });\n  },\n\n  /**\n   * Creates a keyframe animation using the Web Animations API\n   * @param element - The HTML element to animate\n   * @param keyframes - Array of keyframe objects\n   * @param options - Animation options\n   * @returns Animation object\n   * @example\n   * ```typescript\n   * const element = document.querySelector('.box');\n   * const animation = AnimationUtils.createKeyframeAnimation(element, [\n   *   { transform: 'translateX(0)', opacity: 1 },\n   *   { transform: 'translateX(100px)', opacity: 0.5 }\n   * ], {\n   *   duration: 500,\n   *   easing: 'ease-in-out'\n   * });\n   * ```\n   */\n  createKeyframeAnimation(\n    element: HTMLElement,\n    keyframes: Keyframe[],\n    options: KeyframeAnimationOptions = {}\n  ): Animation {\n    return element.animate(keyframes, {\n      duration: 300,\n      easing: \"ease\",\n      fill: \"forwards\",\n      ...options,\n    });\n  },\n\n  /**\n   * Creates a spring physics-based animation\n   * @param element - The HTML element to animate\n   * @param properties - CSS properties to animate\n   * @param options - Spring animation configuration\n   * @returns Promise that resolves when animation completes\n   * @example\n   * ```typescript\n   * const element = document.querySelector('.box');\n   * await AnimationUtils.createSpringAnimation(element, {\n   *   transform: 'translateY(200px)'\n   * }, {\n   *   stiffness: 170,\n   *   damping: 26,\n   *   mass: 1\n   * });\n   * ```\n   */\n  createSpringAnimation(\n    element: HTMLElement,\n    properties: Partial<CSSStyleDeclaration>,\n    options: SpringOptions = {}\n  ): Promise<void> {\n    const { stiffness = 170, damping = 26, mass = 1, duration = 300 } = options;\n\n    return new Promise((resolve) => {\n      const startTime = performance.now();\n      const startValues: { [key: string]: number } = {};\n      const endValues: { [key: string]: number } = {};\n      const velocities: { [key: string]: number } = {};\n\n      // Get start values\n      Object.keys(properties).forEach((key) => {\n        const value = properties[key as keyof CSSStyleDeclaration];\n        if (value !== undefined) {\n          const startValue = parseFloat(\n            getComputedStyle(element)[\n              key as keyof CSSStyleDeclaration\n            ] as string\n          );\n          const endValue = parseFloat(value as string);\n          if (!isNaN(startValue) && !isNaN(endValue)) {\n            startValues[key] = startValue;\n            endValues[key] = endValue;\n            velocities[key] = 0;\n          }\n        }\n      });\n\n      const animate = (currentTime: number) => {\n        const elapsed = currentTime - startTime;\n        if (elapsed >= duration) {\n          Object.keys(endValues).forEach((key) => {\n            (element.style as any)[key] = `${endValues[key]}px`;\n          });\n          resolve();\n          return;\n        }\n\n        Object.keys(startValues).forEach((key) => {\n          const startValue = startValues[key];\n          const endValue = endValues[key];\n          const currentValue = parseFloat(\n            (element.style as any)[key] || startValue\n          );\n          const velocity = velocities[key];\n\n          const displacement = endValue - currentValue;\n          const spring = stiffness * displacement;\n          const damper = damping * velocity;\n          const acceleration = (spring - damper) / mass;\n\n          velocities[key] = velocity + acceleration * (elapsed / 1000);\n          const newValue = currentValue + velocities[key] * (elapsed / 1000);\n          (element.style as any)[key] = `${newValue}px`;\n        });\n\n        requestAnimationFrame(animate);\n      };\n\n      requestAnimationFrame(animate);\n    });\n  },\n\n  /**\n   * Gets all animations currently running on an element\n   * @param element - The HTML element to check\n   * @returns Array of Animation objects\n   * @example\n   * ```typescript\n   * const element = document.querySelector('.box');\n   * const animations = AnimationUtils.getAnimations(element);\n   * ```\n   */\n  getAnimations(element: HTMLElement): Animation[] {\n    return element.getAnimations();\n  },\n\n  /**\n   * Gets the current animation state of an element\n   * @param element - The HTML element to check\n   * @returns Current animation state: 'idle', 'running', or 'paused'\n   * @example\n   * ```typescript\n   * const element = document.querySelector('.box');\n   * const state = AnimationUtils.getAnimationState(element);\n   * if (state === 'running') {\n   *   console.log('Element is currently animating');\n   * }\n   * ```\n   */\n  getAnimationState(element: HTMLElement): \"idle\" | \"running\" | \"paused\" {\n    const animations = element.getAnimations();\n    if (animations.length === 0) {\n      return \"idle\";\n    }\n    return animations.some((animation) => animation.playState === \"running\")\n      ? \"running\"\n      : \"paused\";\n  },\n\n  /**\n   * Checks if an element has any active animations\n   * @param element - The HTML element to check\n   * @returns True if the element has any animations\n   * @example\n   * ```typescript\n   * const element = document.querySelector('.box');\n   * if (AnimationUtils.hasAnimations(element)) {\n   *   console.log('Element has active animations');\n   * }\n   * ```\n   */\n  hasAnimations(element: HTMLElement): boolean {\n    return element.getAnimations().length > 0;\n  },\n\n  /**\n   * Pauses all animations on an element\n   * @param element - The HTML element to pause animations on\n   * @example\n   * ```typescript\n   * const element = document.querySelector('.box');\n   * AnimationUtils.pauseAnimations(element);\n   * ```\n   */\n  pauseAnimations(element: HTMLElement): void {\n    element.getAnimations().forEach((animation) => animation.pause());\n  },\n\n  /**\n   * Resumes all paused animations on an element\n   * @param element - The HTML element to resume animations on\n   * @example\n   * ```typescript\n   * const element = document.querySelector('.box');\n   * AnimationUtils.resumeAnimations(element);\n   * ```\n   */\n  resumeAnimations(element: HTMLElement): void {\n    element.getAnimations().forEach((animation) => animation.play());\n  },\n\n  /**\n   * Reverses the direction of all animations on an element\n   * @param element - The HTML element to reverse animations on\n   * @example\n   * ```typescript\n   * const element = document.querySelector('.box');\n   * AnimationUtils.reverseAnimations(element);\n   * ```\n   */\n  reverseAnimations(element: HTMLElement): void {\n    element.getAnimations().forEach((animation) => animation.reverse());\n  },\n\n  /**\n   * Stops and removes all animations from an element\n   * @param element - The HTML element to stop animations on\n   * @example\n   * ```typescript\n   * const element = document.querySelector('.box');\n   * AnimationUtils.stopAnimations(element);\n   * ```\n   */\n  stopAnimations(element: HTMLElement): void {\n    element.getAnimations().forEach((animation) => animation.cancel());\n  },\n\n  /**\n   * Waits for all animations on an element to complete\n   * @param element - The HTML element to wait for\n   * @returns Promise that resolves when all animations complete\n   * @example\n   * ```typescript\n   * const element = document.querySelector('.box');\n   * await AnimationUtils.waitForAnimations(element);\n   * console.log('All animations completed');\n   * ```\n   */\n  async waitForAnimations(element: HTMLElement): Promise<void> {\n    const animations = element.getAnimations();\n    await Promise.all(animations.map((animation) => animation.finished));\n  },\n};\n"],"names":[],"mappings":"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"}