import { useAnimate, type AnimationSequence } from "framer-motion"; import { Button } from "~/components/ui/button"; import { IconMatrix, type IconType } from "~/components/IconComponents"; import { cn } from "~/lib/utils"; import { forwardRef, useImperativeHandle, type ComponentPropsWithoutRef, } from "react"; const randomNumberBetween = (min: number, max: number) => { return Math.floor(Math.random() * (max - min + 1) + min); }; export interface AnimatedButtonRef { sparkle: () => void; } interface AnimatedButtonProps extends ComponentPropsWithoutRef { sparklesRadius?: number; sparklesNumber?: number; sparklesClassName?: string; sparklesIcon?: IconType; sparklesScale?: [number, number]; } export const AnimatedButton = forwardRef< AnimatedButtonRef, AnimatedButtonProps >( ( { sparklesRadius = 100, sparklesNumber = 20, sparklesClassName = "fill-blue-500 stroke-transparent", sparklesIcon = "star", sparklesScale = [1.5, 2.5], ...props }, ref, ) => { const [scope, animate] = useAnimate(); const Sparkles = () => { const sparkles = Array.from({ length: sparklesNumber }); const sparklesAnimation: AnimationSequence = sparkles.map((_, index) => [ `.sparkle-${index}`, { x: randomNumberBetween(-sparklesRadius, sparklesRadius), y: randomNumberBetween(-sparklesRadius, sparklesRadius), scale: randomNumberBetween(sparklesScale[0], sparklesScale[1]), opacity: 1, }, { duration: 0.4, at: "<", delay: index * 0.01, }, ]); const sparklesFadeOut: AnimationSequence = sparkles.map((_, index) => [ `.sparkle-${index}`, { opacity: 0, scale: 0, }, { duration: 0.3, at: "<", }, ]); const sparklesReset: AnimationSequence = sparkles.map((_, index) => [ `.sparkle-${index}`, { x: 0, y: 0, }, { duration: 0.000001, }, ]); animate([ ...sparklesReset, ["button", { scale: 0.8 }, { duration: 0.1, at: "<" }], ["button", { scale: 1 }, { duration: 0.1 }], ...sparklesAnimation, ["button", { duration: 0.000001 }], ...sparklesFadeOut, ]); }; useImperativeHandle(ref, () => ({ sparkle: Sparkles, })); return (
); }, ); AnimatedButton.displayName = "AnimatedButton";