"use client"; import type { Transition, Variants } from "framer-motion"; /** * Spring-based easing functions matching the CSS tokens */ export const springTransition: Transition = { type: "spring", stiffness: 300, damping: 30, }; export const gentleSpring: Transition = { type: "spring", stiffness: 200, damping: 25, }; export const bouncySpring: Transition = { type: "spring", stiffness: 400, damping: 20, }; /** * Animation variants for entrance animations */ export const fadeIn: Variants = { hidden: { opacity: 0 }, visible: { opacity: 1, transition: { duration: 0.4, ease: [0.16, 1, 0.3, 1] }, }, }; export const fadeInUp: Variants = { hidden: { opacity: 0, y: 20 }, visible: { opacity: 1, y: 0, transition: { duration: 0.5, ease: [0.22, 1, 0.36, 1] }, }, }; export const fadeInScale: Variants = { hidden: { opacity: 0, scale: 0.95, y: 12 }, visible: { opacity: 1, scale: 1, y: 0, transition: { duration: 0.5, ease: [0.34, 1.56, 0.64, 1] }, }, }; export const slideInLeft: Variants = { hidden: { opacity: 0, x: -20 }, visible: { opacity: 1, x: 0, transition: { duration: 0.4, ease: [0.22, 1, 0.36, 1] }, }, }; export const slideInRight: Variants = { hidden: { opacity: 0, x: 20 }, visible: { opacity: 1, x: 0, transition: { duration: 0.4, ease: [0.22, 1, 0.36, 1] }, }, }; /** * Stagger container variants */ export const staggerContainer: Variants = { hidden: { opacity: 0 }, visible: { opacity: 1, transition: { staggerChildren: 0.06, delayChildren: 0.1, }, }, }; export const staggerContainerFast: Variants = { hidden: { opacity: 0 }, visible: { opacity: 1, transition: { staggerChildren: 0.04, delayChildren: 0.05, }, }, }; /** * List item variants for staggered animations */ export const listItem: Variants = { hidden: { opacity: 0, y: 16 }, visible: { opacity: 1, y: 0, transition: springTransition, }, }; export const listItemSpring: Variants = { hidden: { opacity: 0, scale: 0.95, y: 12 }, visible: { opacity: 1, scale: 1, y: 0, transition: { duration: 0.5, ease: [0.34, 1.56, 0.64, 1] }, }, }; /** * Page transition variants */ export const pageTransition: Variants = { hidden: { opacity: 0, y: 8 }, visible: { opacity: 1, y: 0, transition: { duration: 0.35, ease: [0.22, 1, 0.36, 1] }, }, exit: { opacity: 0, y: -8, transition: { duration: 0.2, ease: [0.22, 1, 0.36, 1] }, }, }; /** * Hover scale variant for interactive elements */ export const hoverScale: Variants = { rest: { scale: 1 }, hover: { scale: 1.02, transition: { duration: 0.2, ease: [0.22, 1, 0.36, 1] }, }, tap: { scale: 0.98, transition: { duration: 0.1 }, }, }; /** * Glow pulse variant for accent elements */ export const glowPulse: Variants = { initial: { opacity: 0.6 }, animate: { opacity: [0.6, 1, 0.6], transition: { duration: 2, repeat: Infinity, ease: "easeInOut", }, }, }; /** * Draw line variant for SVG paths */ export const drawLine: Variants = { hidden: { pathLength: 0, opacity: 0 }, visible: { pathLength: 1, opacity: 1, transition: { duration: 1.2, ease: [0.4, 0, 0.2, 1] }, }, }; /** * Ambient float animation */ export const float: Variants = { initial: { y: 0 }, animate: { y: [-4, 4, -4], transition: { duration: 6, repeat: Infinity, ease: "easeInOut", }, }, }; /** * Reduced motion check helper * Returns true if user prefers reduced motion */ export function prefersReducedMotion(): boolean { if (typeof window === "undefined") return false; return window.matchMedia("(prefers-reduced-motion: reduce)").matches; }