feat: Initialize portfolio project with core pages, UI components, and configuration files.
This commit is contained in:
1 parent
aa07d6faeb
commit
0523052864
38 files changed
+1165
-460
No files matched your search
+43
-27
@@ -1,7 +1,15 @@
|
||||
'use client';
|
||||
"use client";
|
||||
|
||||
import { ElementType, useEffect, useRef, useState, createElement, useMemo, useCallback } from 'react';
|
||||
import { gsap } from 'gsap';
|
||||
import {
|
||||
ElementType,
|
||||
useEffect,
|
||||
useRef,
|
||||
useState,
|
||||
createElement,
|
||||
useMemo,
|
||||
useCallback,
|
||||
} from "react";
|
||||
import { gsap } from "gsap";
|
||||
|
||||
interface TextTypeProps {
|
||||
className?: string;
|
||||
@@ -26,17 +34,17 @@ interface TextTypeProps {
|
||||
|
||||
const TextType = ({
|
||||
text,
|
||||
as: Component = 'div',
|
||||
as: Component = "div",
|
||||
typingSpeed = 50,
|
||||
initialDelay = 0,
|
||||
pauseDuration = 2000,
|
||||
deletingSpeed = 30,
|
||||
loop = true,
|
||||
className = '',
|
||||
className = "",
|
||||
showCursor = true,
|
||||
hideCursorWhileTyping = false,
|
||||
cursorCharacter = '|',
|
||||
cursorClassName = '',
|
||||
cursorCharacter = "|",
|
||||
cursorClassName = "",
|
||||
cursorBlinkDuration = 0.5,
|
||||
textColors = [],
|
||||
variableSpeed,
|
||||
@@ -45,7 +53,7 @@ const TextType = ({
|
||||
reverseMode = false,
|
||||
...props
|
||||
}: TextTypeProps & React.HTMLAttributes<HTMLElement>) => {
|
||||
const [displayedText, setDisplayedText] = useState('');
|
||||
const [displayedText, setDisplayedText] = useState("");
|
||||
const [currentCharIndex, setCurrentCharIndex] = useState(0);
|
||||
const [isDeleting, setIsDeleting] = useState(false);
|
||||
const [currentTextIndex, setCurrentTextIndex] = useState(0);
|
||||
@@ -53,7 +61,10 @@ const TextType = ({
|
||||
const cursorRef = useRef<HTMLSpanElement>(null);
|
||||
const containerRef = useRef<HTMLElement>(null);
|
||||
|
||||
const textArray = useMemo(() => (Array.isArray(text) ? text : [text]), [text]);
|
||||
const textArray = useMemo(
|
||||
() => (Array.isArray(text) ? text : [text]),
|
||||
[text],
|
||||
);
|
||||
|
||||
const getRandomSpeed = useCallback(() => {
|
||||
if (!variableSpeed) return typingSpeed;
|
||||
@@ -62,7 +73,7 @@ const TextType = ({
|
||||
}, [variableSpeed, typingSpeed]);
|
||||
|
||||
const getCurrentTextColor = () => {
|
||||
if (textColors.length === 0) return '#ffffff';
|
||||
if (textColors.length === 0) return "#ffffff";
|
||||
return textColors[currentTextIndex % textColors.length];
|
||||
};
|
||||
|
||||
@@ -70,14 +81,14 @@ const TextType = ({
|
||||
if (!startOnVisible || !containerRef.current) return;
|
||||
|
||||
const observer = new IntersectionObserver(
|
||||
entries => {
|
||||
entries.forEach(entry => {
|
||||
(entries) => {
|
||||
entries.forEach((entry) => {
|
||||
if (entry.isIntersecting) {
|
||||
setIsVisible(true);
|
||||
}
|
||||
});
|
||||
},
|
||||
{ threshold: 0.1 }
|
||||
{ threshold: 0.1 },
|
||||
);
|
||||
|
||||
observer.observe(containerRef.current);
|
||||
@@ -92,7 +103,7 @@ const TextType = ({
|
||||
duration: cursorBlinkDuration,
|
||||
repeat: -1,
|
||||
yoyo: true,
|
||||
ease: 'power2.inOut'
|
||||
ease: "power2.inOut",
|
||||
});
|
||||
}
|
||||
}, [showCursor, cursorBlinkDuration]);
|
||||
@@ -103,11 +114,13 @@ const TextType = ({
|
||||
let timeout: NodeJS.Timeout;
|
||||
|
||||
const currentText = textArray[currentTextIndex];
|
||||
const processedText = reverseMode ? currentText.split('').reverse().join('') : currentText;
|
||||
const processedText = reverseMode
|
||||
? currentText.split("").reverse().join("")
|
||||
: currentText;
|
||||
|
||||
const executeTypingAnimation = () => {
|
||||
if (isDeleting) {
|
||||
if (displayedText === '') {
|
||||
if (displayedText === "") {
|
||||
setIsDeleting(false);
|
||||
if (currentTextIndex === textArray.length - 1 && !loop) {
|
||||
return;
|
||||
@@ -117,22 +130,24 @@ const TextType = ({
|
||||
onSentenceComplete(textArray[currentTextIndex], currentTextIndex);
|
||||
}
|
||||
|
||||
setCurrentTextIndex(prev => (prev + 1) % textArray.length);
|
||||
setCurrentTextIndex((prev) => (prev + 1) % textArray.length);
|
||||
setCurrentCharIndex(0);
|
||||
timeout = setTimeout(() => {}, pauseDuration);
|
||||
} else {
|
||||
timeout = setTimeout(() => {
|
||||
setDisplayedText(prev => prev.slice(0, -1));
|
||||
setDisplayedText((prev) => prev.slice(0, -1));
|
||||
}, deletingSpeed);
|
||||
}
|
||||
} else {
|
||||
if (currentCharIndex < processedText.length) {
|
||||
timeout = setTimeout(
|
||||
() => {
|
||||
setDisplayedText(prev => prev + processedText[currentCharIndex]);
|
||||
setCurrentCharIndex(prev => prev + 1);
|
||||
setDisplayedText(
|
||||
(prev) => prev + processedText[currentCharIndex],
|
||||
);
|
||||
setCurrentCharIndex((prev) => prev + 1);
|
||||
},
|
||||
variableSpeed ? getRandomSpeed() : typingSpeed
|
||||
variableSpeed ? getRandomSpeed() : typingSpeed,
|
||||
);
|
||||
} else if (textArray.length > 1) {
|
||||
timeout = setTimeout(() => {
|
||||
@@ -142,7 +157,7 @@ const TextType = ({
|
||||
}
|
||||
};
|
||||
|
||||
if (currentCharIndex === 0 && !isDeleting && displayedText === '') {
|
||||
if (currentCharIndex === 0 && !isDeleting && displayedText === "") {
|
||||
timeout = setTimeout(executeTypingAnimation, initialDelay);
|
||||
} else {
|
||||
executeTypingAnimation();
|
||||
@@ -163,18 +178,19 @@ const TextType = ({
|
||||
isVisible,
|
||||
reverseMode,
|
||||
variableSpeed,
|
||||
onSentenceComplete
|
||||
onSentenceComplete,
|
||||
]);
|
||||
|
||||
const shouldHideCursor =
|
||||
hideCursorWhileTyping && (currentCharIndex < textArray[currentTextIndex].length || isDeleting);
|
||||
hideCursorWhileTyping &&
|
||||
(currentCharIndex < textArray[currentTextIndex].length || isDeleting);
|
||||
|
||||
return createElement(
|
||||
Component,
|
||||
{
|
||||
ref: containerRef,
|
||||
className: `inline-block whitespace-pre-wrap tracking-tight ${className}`,
|
||||
...props
|
||||
...props,
|
||||
},
|
||||
<span className="inline" style={{ color: getCurrentTextColor() }}>
|
||||
{displayedText}
|
||||
@@ -182,11 +198,11 @@ const TextType = ({
|
||||
showCursor && (
|
||||
<span
|
||||
ref={cursorRef}
|
||||
className={`ml-1 inline-block opacity-100 ${shouldHideCursor ? 'hidden' : ''} ${cursorClassName}`}
|
||||
className={`ml-1 inline-block opacity-100 ${shouldHideCursor ? "hidden" : ""} ${cursorClassName}`}
|
||||
>
|
||||
{cursorCharacter}
|
||||
</span>
|
||||
)
|
||||
),
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
Reference in new issue
Block a user