{ "name": "matrix-text", "type": "registry:component", "dependencies": [ "motion" ], "files": [ { "type": "registry:component", "content": "\"use client\";\n\n/**\n * @author: @dorianbaffier\n * @description: Matrix Text\n * @version: 1.0.0\n * @date: 2025-06-26\n * @license: MIT\n * @website: https://kokonutui.com\n * @github: https://github.com/kokonut-labs/kokonutui\n */\n\nimport { motion } from \"motion/react\";\nimport { useCallback, useEffect, useMemo, useState } from \"react\";\nimport { cn } from \"@/lib/utils\";\n\ninterface LetterState {\n char: string;\n isMatrix: boolean;\n isSpace: boolean;\n}\n\ninterface MatrixTextProps {\n text?: string;\n className?: string;\n initialDelay?: number;\n letterAnimationDuration?: number;\n letterInterval?: number;\n}\n\nconst MatrixText = ({\n text = \"HelloWorld!\",\n className,\n initialDelay = 200,\n letterAnimationDuration = 500,\n letterInterval = 100,\n}: MatrixTextProps) => {\n const [letters, setLetters] = useState(() =>\n text.split(\"\").map((char) => ({\n char,\n isMatrix: false,\n isSpace: char === \" \",\n }))\n );\n const [isAnimating, setIsAnimating] = useState(false);\n\n const getRandomChar = useCallback(\n () => (Math.random() > 0.5 ? \"1\" : \"0\"),\n []\n );\n\n const animateLetter = useCallback(\n (index: number) => {\n if (index >= text.length) return;\n\n requestAnimationFrame(() => {\n setLetters((prev) => {\n const newLetters = [...prev];\n if (!newLetters[index].isSpace) {\n newLetters[index] = {\n ...newLetters[index],\n char: getRandomChar(),\n isMatrix: true,\n };\n }\n return newLetters;\n });\n\n setTimeout(() => {\n setLetters((prev) => {\n const newLetters = [...prev];\n newLetters[index] = {\n ...newLetters[index],\n char: text[index],\n isMatrix: false,\n };\n return newLetters;\n });\n }, letterAnimationDuration);\n });\n },\n [getRandomChar, text, letterAnimationDuration]\n );\n\n const startAnimation = useCallback(() => {\n if (isAnimating) return;\n\n setIsAnimating(true);\n let currentIndex = 0;\n\n const animate = () => {\n if (currentIndex >= text.length) {\n setIsAnimating(false);\n return;\n }\n\n animateLetter(currentIndex);\n currentIndex++;\n setTimeout(animate, letterInterval);\n };\n\n animate();\n }, [animateLetter, text, isAnimating, letterInterval]);\n\n useEffect(() => {\n const timer = setTimeout(startAnimation, initialDelay);\n return () => clearTimeout(timer);\n }, []);\n\n const motionVariants = useMemo(\n () => ({\n // initial: {\n // color: \"rgb(var(--foreground-rgb))\",\n // },\n matrix: {\n color: \"#00ff00\",\n textShadow: \"0 2px 4px rgba(0, 255, 0, 0.5)\",\n },\n // normal: {\n // color: \"rgb(var(--foreground-rgb))\",\n // textShadow: \"none\",\n // },\n }),\n []\n );\n\n return (\n \n
\n
\n {letters.map((letter, index) => (\n \n {letter.isSpace ? \"\\u00A0\" : letter.char}\n \n ))}\n
\n
\n \n );\n};\n\nexport default MatrixText;\n", "path": "/components/kokonutui/matrix-text.tsx", "target": "components/kokonutui/matrix-text.tsx" } ] }