|
import PropTypes from 'prop-types' |
|
import { forwardRef } from 'react' |
|
|
|
import { motion, useCycle } from 'framer-motion' |
|
|
|
|
|
|
|
const AnimateButton = forwardRef(function AnimateButton({ children, type, direction, offset, scale }, ref) { |
|
let offset1 |
|
let offset2 |
|
switch (direction) { |
|
case 'up': |
|
case 'left': |
|
offset1 = offset |
|
offset2 = 0 |
|
break |
|
case 'right': |
|
case 'down': |
|
default: |
|
offset1 = 0 |
|
offset2 = offset |
|
break |
|
} |
|
|
|
const [x, cycleX] = useCycle(offset1, offset2) |
|
const [y, cycleY] = useCycle(offset1, offset2) |
|
|
|
switch (type) { |
|
case 'rotate': |
|
return ( |
|
<motion.div |
|
ref={ref} |
|
animate={{ rotate: 360 }} |
|
transition={{ |
|
repeat: Infinity, |
|
repeatType: 'loop', |
|
duration: 2, |
|
repeatDelay: 0 |
|
}} |
|
> |
|
{children} |
|
</motion.div> |
|
) |
|
case 'slide': |
|
if (direction === 'up' || direction === 'down') { |
|
return ( |
|
<motion.div |
|
ref={ref} |
|
animate={{ y: y !== undefined ? y : '' }} |
|
onHoverEnd={() => cycleY()} |
|
onHoverStart={() => cycleY()} |
|
> |
|
{children} |
|
</motion.div> |
|
) |
|
} |
|
return ( |
|
<motion.div ref={ref} animate={{ x: x !== undefined ? x : '' }} onHoverEnd={() => cycleX()} onHoverStart={() => cycleX()}> |
|
{children} |
|
</motion.div> |
|
) |
|
|
|
case 'scale': |
|
default: |
|
if (typeof scale === 'number') { |
|
scale = { |
|
hover: scale, |
|
tap: scale |
|
} |
|
} |
|
return ( |
|
<motion.div ref={ref} whileHover={{ scale: scale?.hover }} whileTap={{ scale: scale?.tap }}> |
|
{children} |
|
</motion.div> |
|
) |
|
} |
|
}) |
|
|
|
AnimateButton.propTypes = { |
|
children: PropTypes.node, |
|
offset: PropTypes.number, |
|
type: PropTypes.oneOf(['slide', 'scale', 'rotate']), |
|
direction: PropTypes.oneOf(['up', 'down', 'left', 'right']), |
|
scale: PropTypes.oneOfType([PropTypes.number, PropTypes.object]) |
|
} |
|
|
|
AnimateButton.defaultProps = { |
|
type: 'scale', |
|
offset: 10, |
|
direction: 'right', |
|
scale: { |
|
hover: 1, |
|
tap: 0.9 |
|
} |
|
} |
|
|
|
export default AnimateButton |
|
|