mirror of
https://github.com/massbug/judge4c.git
synced 2025-05-18 23:56:33 +00:00
53 lines
1.5 KiB
TypeScript
53 lines
1.5 KiB
TypeScript
|
"use client";
|
||
|
|
||
|
import { motion } from "framer-motion";
|
||
|
import { useTranslations } from "next-intl";
|
||
|
import { useEffect, useState, useMemo } from "react";
|
||
|
|
||
|
export function TypingEffect() {
|
||
|
const t = useTranslations("HomePage.MainView.features");
|
||
|
const texts = useMemo(
|
||
|
() => [t("feature1"), t("feature2"), t("feature3")],
|
||
|
[t]
|
||
|
);
|
||
|
const [index, setIndex] = useState(0);
|
||
|
const [displayText, setDisplayText] = useState("");
|
||
|
const [isDeleting, setIsDeleting] = useState(false);
|
||
|
|
||
|
useEffect(() => {
|
||
|
const handleTyping = () => {
|
||
|
const currentText = texts[index];
|
||
|
|
||
|
if (isDeleting) {
|
||
|
setDisplayText(currentText.substring(0, displayText.length - 1));
|
||
|
} else {
|
||
|
setDisplayText(currentText.substring(0, displayText.length + 1));
|
||
|
}
|
||
|
|
||
|
if (!isDeleting && displayText === currentText) {
|
||
|
setTimeout(() => setIsDeleting(true), 1000);
|
||
|
} else if (isDeleting && displayText === "") {
|
||
|
setIsDeleting(false);
|
||
|
setIndex((prevIndex) => (prevIndex + 1) % texts.length);
|
||
|
}
|
||
|
};
|
||
|
|
||
|
const typingSpeed = isDeleting ? 50 : 100;
|
||
|
const timer = setTimeout(handleTyping, typingSpeed);
|
||
|
|
||
|
return () => clearTimeout(timer);
|
||
|
}, [displayText, isDeleting, index, texts]);
|
||
|
|
||
|
return (
|
||
|
<motion.div
|
||
|
initial={{ opacity: 0 }}
|
||
|
animate={{ opacity: 1 }}
|
||
|
exit={{ opacity: 0 }}
|
||
|
className="inline-block"
|
||
|
>
|
||
|
{displayText}
|
||
|
<span className="blinking-cursor">|</span>
|
||
|
</motion.div>
|
||
|
);
|
||
|
}
|