63 lines
2.3 KiB
TypeScript
63 lines
2.3 KiB
TypeScript
'use client';
|
|
import type { Transition, Variants } from 'motion/react';
|
|
import type { HTMLAttributes } from 'react';
|
|
import { forwardRef, useCallback, useImperativeHandle, useRef } from 'react';
|
|
import { motion, useAnimation } from 'motion/react';
|
|
import { cn } from '@/lib/utils';
|
|
export interface HomeIconHandle {
|
|
startAnimation: () => void;
|
|
stopAnimation: () => void;
|
|
}
|
|
interface HomeIconProps extends HTMLAttributes<HTMLDivElement> {
|
|
size?: number;
|
|
}
|
|
const DEFAULT_TRANSITION: Transition = {
|
|
duration: 0.6,
|
|
opacity: { duration: 0.2 },
|
|
};
|
|
const PATH_VARIANTS: Variants = {
|
|
normal: {
|
|
pathLength: 1,
|
|
opacity: 1,
|
|
},
|
|
animate: {
|
|
opacity: [0, 1],
|
|
pathLength: [0, 1],
|
|
},
|
|
};
|
|
const HomeIcon = forwardRef<HomeIconHandle, HomeIconProps>(({ onMouseEnter, onMouseLeave, className, size = 28, ...props }, ref) => {
|
|
const controls = useAnimation();
|
|
const isControlledRef = useRef(false);
|
|
useImperativeHandle(ref, () => {
|
|
isControlledRef.current = true;
|
|
return {
|
|
startAnimation: () => controls.start('animate'),
|
|
stopAnimation: () => controls.start('normal'),
|
|
};
|
|
});
|
|
const handleMouseEnter = useCallback((e: React.MouseEvent<HTMLDivElement>) => {
|
|
if (!isControlledRef.current) {
|
|
controls.start('animate');
|
|
}
|
|
else {
|
|
onMouseEnter?.(e);
|
|
}
|
|
}, [controls, onMouseEnter]);
|
|
const handleMouseLeave = useCallback((e: React.MouseEvent<HTMLDivElement>) => {
|
|
if (!isControlledRef.current) {
|
|
controls.start('normal');
|
|
}
|
|
else {
|
|
onMouseLeave?.(e);
|
|
}
|
|
}, [controls, onMouseLeave]);
|
|
return (<div className={cn(className)} onMouseEnter={handleMouseEnter} onMouseLeave={handleMouseLeave} {...props}>
|
|
<svg xmlns="http://www.w3.org/2000/svg" width={size} height={size} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
|
|
<path d="M3 10a2 2 0 0 1 .709-1.528l7-5.999a2 2 0 0 1 2.582 0l7 5.999A2 2 0 0 1 21 10v9a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z"/>
|
|
<motion.path d="M15 21v-8a1 1 0 0 0-1-1h-4a1 1 0 0 0-1 1v8" variants={PATH_VARIANTS} transition={DEFAULT_TRANSITION} animate={controls}/>
|
|
</svg>
|
|
</div>);
|
|
});
|
|
HomeIcon.displayName = 'HomeIcon';
|
|
export { HomeIcon };
|