Spaces:
Sleeping
Sleeping
| import React, { useState } from 'react'; | |
| const morseCodeMap = { | |
| 'A': '.-', 'B': '-...', 'C': '-.-.', 'D': '-..', 'E': '.', 'F': '..-.', 'G': '--.', 'H': '....', | |
| 'I': '..', 'J': '.---', 'K': '-.-', 'L': '.-..', 'M': '--', 'N': '-.', 'O': '---', 'P': '.--.', | |
| 'Q': '--.-', 'R': '.-.', 'S': '...', 'T': '-', 'U': '..-', 'V': '...-', 'W': '.--', 'X': '-..-', | |
| 'Y': '-.--', 'Z': '--..', | |
| '1': '.----', '2': '..---', '3': '...--', '4': '....-', '5': '.....', '6': '-....', '7': '--...', | |
| '8': '---..', '9': '----.', '0': '-----', | |
| ' ': '/' | |
| }; | |
| // Create a reverse map for decoding | |
| const reverseMorseCodeMap = Object.entries(morseCodeMap).reduce((acc, [key, value]) => { | |
| acc[value] = key; | |
| return acc; | |
| }, {}); | |
| const MorseCodeConverter = ({ addToMessage }) => { | |
| const [input, setInput] = useState(''); | |
| const [output, setOutput] = useState(''); | |
| const [copied, setCopied] = useState(false); | |
| const [toMorse, setToMorse] = useState(true); // true for text to morse, false for morse to text | |
| const convertToMorse = (text) => { | |
| let morse = ''; | |
| for (let char of text.toUpperCase()) { | |
| if (morseCodeMap[char]) { | |
| morse += morseCodeMap[char] + ' '; | |
| } else { | |
| morse += '? '; // Represent unknown characters | |
| } | |
| } | |
| setOutput(morse.trim()); | |
| }; | |
| const convertFromMorse = (morse) => { | |
| let text = ''; | |
| const morseChars = morse.split(' '); | |
| for (let morseChar of morseChars) { | |
| if (reverseMorseCodeMap[morseChar]) { | |
| text += reverseMorseCodeMap[morseChar]; | |
| } else if (morseChar === '/') { | |
| text += ' '; | |
| } | |
| } | |
| setOutput(text); | |
| }; | |
| const handleInputChange = (e) => { | |
| const newText = e.target.value; | |
| setInput(newText); | |
| if (toMorse) { | |
| convertToMorse(newText); | |
| } else { | |
| convertFromMorse(newText); | |
| } | |
| }; | |
| const copyToClipboard = () => { | |
| navigator.clipboard.writeText(output); | |
| setCopied(true); | |
| setTimeout(() => setCopied(false), 2000); | |
| }; | |
| const swapConversion = () => { | |
| const oldInput = input; | |
| setInput(output); | |
| setOutput(oldInput); | |
| setToMorse(!toMorse); | |
| }; | |
| return ( | |
| <div className="p-6 bg-gradient-to-br from-gray-900 to-black rounded-lg border border-gray-800 hover-glow transition-all duration-300"> | |
| <h2 className="text-3xl font-bold mb-6 text-white flex items-center gap-2"> | |
| <span className="text-purple-500">⚡</span> | |
| Morse Code Converter | |
| </h2> | |
| <div className="grid grid-cols-1 md:grid-cols-[1fr_auto_1fr] gap-6 items-center"> | |
| <div className="space-y-2"> | |
| <label htmlFor="morse-input" className="block text-sm font-medium text-gray-300 mb-2"> | |
| {toMorse ? 'Text Input' : 'Morse Code Input'} | |
| </label> | |
| <textarea | |
| id="morse-input" | |
| className="w-full h-40 p-4 bg-gray-950 border-2 border-gray-700 rounded-lg text-white focus:ring-2 focus:ring-purple-500 focus:border-purple-500 transition-all duration-300 hover:border-gray-600 resize-none" | |
| placeholder={toMorse ? 'Enter text...' : 'Enter Morse code...'} | |
| value={input} | |
| onChange={handleInputChange} | |
| /> | |
| </div> | |
| <div className="flex justify-center"> | |
| <button | |
| onClick={swapConversion} | |
| className="p-3 bg-gradient-to-br from-purple-600 to-purple-800 text-white rounded-full hover:from-purple-500 hover:to-purple-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-purple-500 transition-all duration-300 hover:scale-110 active:scale-95 shadow-lg hover:shadow-purple-500/50" | |
| title="Swap conversion direction" | |
| > | |
| <svg xmlns="http://www.w3.org/2000/svg" className="h-6 w-6" fill="none" viewBox="0 0 24 24" stroke="currentColor"> | |
| <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M8 7h12m0 0l-4-4m4 4l-4 4m2 5H4m0 0l4 4m-4-4l4-4" /> | |
| </svg> | |
| </button> | |
| </div> | |
| <div className="space-y-2"> | |
| <label htmlFor="morse-output" className="block text-sm font-medium text-gray-300 mb-2"> | |
| {toMorse ? 'Morse Code Output' : 'Text Output'} | |
| </label> | |
| <div id="morse-output" className="w-full h-40 p-4 bg-gray-950 border-2 border-gray-700 rounded-lg text-white relative overflow-auto hover:border-gray-600 transition-all duration-300"> | |
| <div className="break-words">{output || <span className="text-gray-500">Output will appear here...</span>}</div> | |
| {output && ( | |
| <div className="absolute top-2 right-2 flex flex-col gap-2"> | |
| <button | |
| onClick={copyToClipboard} | |
| className="px-4 py-2 bg-gradient-to-r from-blue-600 to-blue-700 text-white rounded-md hover:from-blue-500 hover:to-blue-600 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500 transition-all duration-300 shadow-md hover:shadow-lg hover:scale-105 active:scale-95" | |
| > | |
| {copied ? '✓ Copied!' : '📋 Copy'} | |
| </button> | |
| <button | |
| onClick={() => addToMessage(output)} | |
| className="px-4 py-2 bg-gradient-to-r from-green-600 to-green-700 text-white rounded-md hover:from-green-500 hover:to-green-600 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-green-500 transition-all duration-300 shadow-md hover:shadow-lg hover:scale-105 active:scale-95" | |
| > | |
| ➕ Add | |
| </button> | |
| </div> | |
| )} | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| ); | |
| }; | |
| export default MorseCodeConverter; | |