'use client'; import * as React from 'react'; import { type HTMLMotionProps, motion } from 'motion/react'; import { getStrictContext } from '@/lib/utils/get-strict-context'; import { Slot, type WithAsChild, } from '@/components/animate-ui/primitives/animate/slot'; type Ripple = { id: number; x: number; y: number; }; type RippleButtonContextType = { ripples: Ripple[]; setRipples: (ripples: Ripple[]) => void; }; const [RippleButtonProvider, useRippleButton] = getStrictContext('RippleButtonContext'); type RippleButtonProps = WithAsChild< HTMLMotionProps<'button'> & { hoverScale?: number; tapScale?: number; } >; function RippleButton({ ref, onClick, hoverScale = 1, tapScale = 0.95, asChild = false, style, ...props }: RippleButtonProps) { const [ripples, setRipples] = React.useState([]); const buttonRef = React.useRef(null); React.useImperativeHandle(ref, () => buttonRef.current as HTMLButtonElement); const createRipple = React.useCallback( (event: React.MouseEvent) => { const button = buttonRef.current; if (!button) return; const rect = button.getBoundingClientRect(); const x = event.clientX - rect.left; const y = event.clientY - rect.top; const newRipple: Ripple = { id: Date.now(), x, y, }; setRipples((prev) => [...prev, newRipple]); setTimeout(() => { setRipples((prev) => prev.filter((r) => r.id !== newRipple.id)); }, 600); }, [], ); const handleClick = React.useCallback( (event: React.MouseEvent) => { createRipple(event); if (onClick) { onClick(event); } }, [createRipple, onClick], ); const Component = asChild ? Slot : motion.button; return ( ); } type RippleButtonRipplesProps = WithAsChild< HTMLMotionProps<'span'> & { color?: string; scale?: number; } >; function RippleButtonRipples({ color = 'var(--ripple-button-ripple-color)', scale = 10, transition = { duration: 0.6, ease: 'easeOut' }, asChild = false, style, ...props }: RippleButtonRipplesProps) { const { ripples } = useRippleButton(); const Component = asChild ? Slot : motion.span; return ripples.map((ripple) => ( )); } export { RippleButton, RippleButtonRipples, type RippleButtonProps, type RippleButtonRipplesProps, };