"use client"; import type { HTMLAttributes, MouseEvent } from "react"; import { forwardRef, useCallback, useEffect, useImperativeHandle, useRef } from "react"; import { motion, useAnimation, useReducedMotion, type Variants } from "framer-motion"; import { cn } from "../../lib/utils"; export interface FileTextIconHandle { startAnimation: () => void; stopAnimation: () => void; } interface FileTextIconProps extends HTMLAttributes { size?: number; active?: boolean; } const FILE_TEXT_LINE_VARIANTS: Variants = { normal: { pathLength: 1, pathOffset: 0 }, animate: (delay: number) => ({ pathLength: [1, 0, 1], pathOffset: [0, 1, 0], transition: { duration: 0.7, delay, ease: "easeInOut" } }), active: (delay: number) => ({ pathLength: [1, 0, 1], pathOffset: [0, 1, 0], transition: { duration: 0.7, delay, ease: "easeInOut", repeat: Number.POSITIVE_INFINITY, repeatDelay: 1.1 } }) }; const FileTextIcon = forwardRef( ( { active = false, onMouseEnter, onMouseLeave, className, size = 28, ...props }, ref ) => { const controls = useAnimation(); const reduceMotion = useReducedMotion(); const isControlledRef = useRef(false); const startAnimation = useCallback(() => { if (reduceMotion) { return; } void controls.start(active ? "active" : "animate"); }, [active, controls, reduceMotion]); const stopAnimation = useCallback(() => { void controls.start("normal"); }, [controls]); useImperativeHandle(ref, () => { isControlledRef.current = true; return { startAnimation, stopAnimation }; }); useEffect(() => { if (active) { startAnimation(); return; } stopAnimation(); }, [active, startAnimation, stopAnimation]); const handleMouseEnter = useCallback( (event: MouseEvent) => { if (isControlledRef.current) { onMouseEnter?.(event); } else { startAnimation(); } }, [onMouseEnter, startAnimation] ); const handleMouseLeave = useCallback( (event: MouseEvent) => { if (isControlledRef.current) { onMouseLeave?.(event); } else { stopAnimation(); } }, [onMouseLeave, stopAnimation] ); return (
); } ); FileTextIcon.displayName = "FileTextIcon"; export { FileTextIcon };