Multi Tool Hub
import React, { useState } from 'react'; import { Wrench, X, Image as ImageIcon, Video, Mic, Scissors, Calendar, CreditCard, DollarSign, QrCode, Lock, Type, Code, Palette, Speaker, FileJson, Ruler, Activity, Watch, Search } from 'lucide-react'; import { Tool } from './types'; import * as Tools from './components/Tools'; const toolList: Tool[] = [ { id: 'img-conv', title: 'Image Converter', description: 'Convert JPG, PNG, WEBP', icon: ImageIcon, category: 'media' }, { id: 'img-comp', title: 'Image Compressor', description: 'Reduce image file size', icon: ImageIcon, category: 'media' }, { id: 'img-crop', title: 'Image Cropper', description: 'Crop images easily', icon: Scissors, category: 'media' }, { id: 'vid-conv', title: 'Video Converter', description: 'MP4 to WebM conversion', icon: Video, category: 'media' }, { id: 'aud-conv', title: 'Audio Converter', description: 'Convert audio to WAV', icon: Speaker, category: 'media' }, { id: 'aud-trim', title: 'Audio Trimmer', description: 'Trim audio clips', icon: Scissors, category: 'media' }, { id: 'age-calc', title: 'Age Calculator', description: 'Calculate precise age', icon: Calendar, category: 'calc' }, { id: 'emi-calc', title: 'EMI Calculator', description: 'Loan EMI calculation', icon: CreditCard, category: 'calc' }, { id: 'sip-calc', title: 'SIP Calculator', description: 'Investment returns', icon: DollarSign, category: 'calc' }, { id: 'qr-gen', title: 'QR Generator', description: 'Create QR codes', icon: QrCode, category: 'utility' }, { id: 'pass-gen', title: 'Password Generator', description: 'Secure password creation', icon: Lock, category: 'utility' }, { id: 'word-cnt', title: 'Word Counter', description: 'Count words & chars', icon: Type, category: 'text' }, { id: 'base64', title: 'Base64 Tool', description: 'Encode/Decode text', icon: Code, category: 'dev' }, { id: 'color', title: 'Color Picker', description: 'Get HEX, RGB, HSL', icon: Palette, category: 'dev' }, { id: 'tts', title: 'Text to Speech', description: 'Listen to text', icon: Speaker, category: 'text' }, { id: 'stt', title: 'Speech to Text', description: 'Voice typing', icon: Mic, category: 'text' }, { id: 'json', title: 'JSON Formatter', description: 'Prettify JSON', icon: FileJson, category: 'dev' }, { id: 'unit', title: 'Unit Converter', description: 'Length, Weight, Temp', icon: Ruler, category: 'calc' }, { id: 'bmi', title: 'BMI Calculator', description: 'Check Body Mass Index', icon: Activity, category: 'calc' }, { id: 'timer', title: 'Timer / Stopwatch', description: 'Manage time', icon: Watch, category: 'utility' }, ]; const App: React.FC = () => { const [activeToolId, setActiveToolId] = useState(null); const [searchTerm, setSearchTerm] = useState(''); const activeTool = toolList.find(t => t.id === activeToolId); const filteredTools = toolList.filter(t => t.title.toLowerCase().includes(searchTerm.toLowerCase()) || t.description.toLowerCase().includes(searchTerm.toLowerCase()) ); const renderTool = (id: string) => { switch(id) { case 'img-conv': return ; case 'img-comp': return ; case 'img-crop': return ; case 'vid-conv': return ; case 'aud-conv': return ; case 'aud-trim': return ; case 'age-calc': return ; case 'emi-calc': return ; case 'sip-calc': return ; case 'qr-gen': return ; case 'pass-gen': return ; case 'word-cnt': return ; case 'base64': return ; case 'color': return ; case 'tts': return ; case 'stt': return ; case 'json': return ; case 'unit': return ; case 'bmi': return ; case 'timer': return ; default: return null; } }; return (
{/* Header */}

Multi Tool Hub

setSearchTerm(e.target.value)} />
{/* Grid Layout */}
{filteredTools.map(tool => (
setActiveToolId(tool.id)} className="bg-card-bg p-6 rounded-lg cursor-pointer group transition-all duration-300 hover:bg-gold hover:shadow-[0_4px_20px_rgba(255,215,0,0.2)] hover:-translate-y-1" >

{tool.title}

{tool.description}

))}
{filteredTools.length === 0 && (

No tools found matching your search.

)}
{/* Tool Modal */} {activeTool && (

{activeTool.title}

{renderTool(activeTool.id)}
)}
); }; export default App; import React, { useState, useRef, useEffect, useCallback } from 'react'; import { Upload, Download, Play, Pause, RefreshCw, scissors, Mic, Volume2, Copy, Check, Scissors, Calculator, Clock, Palette, FileText, Code, Type, Ruler } from 'lucide-react'; import { AudioProcessResult, UnitType } from '../types'; // --- Shared UI Components --- const Button: React.FC> = ({ className, ...props }) => ( )} ); }; // --- 2. Image Compressor --- export const ImageCompressor = () => { const [preview, setPreview] = useState(null); const [quality, setQuality] = useState(0.8); const canvasRef = useRef(null); const imgRef = useRef(new Image()); const handleFile = (e: React.ChangeEvent) => { const file = e.target.files?.[0]; if (file) { const url = URL.createObjectURL(file); imgRef.current.onload = () => { if (canvasRef.current) { canvasRef.current.width = imgRef.current.width; canvasRef.current.height = imgRef.current.height; const ctx = canvasRef.current.getContext('2d'); ctx?.drawImage(imgRef.current, 0, 0); updatePreview(quality); } }; imgRef.current.src = url; } }; const updatePreview = (q: number) => { if (canvasRef.current) { setPreview(canvasRef.current.toDataURL('image/jpeg', q)); } }; return (
{ const q = parseFloat(e.target.value); setQuality(q); updatePreview(q); }} className="accent-gold w-full" />
{preview && ( <> Compressed )}
); }; // --- 3. Image Cropper (Simple Center Crop) --- export const ImageCropper = () => { const [src, setSrc] = useState(null); const canvasRef = useRef(null); const handleFile = (e: React.ChangeEvent) => { const file = e.target.files?.[0]; if(file) setSrc(URL.createObjectURL(file)); }; const crop = () => { const canvas = canvasRef.current; if(!canvas || !src) return; const img = new Image(); img.onload = () => { // Square crop from center const size = Math.min(img.width, img.height); canvas.width = size; canvas.height = size; const ctx = canvas.getContext('2d'); ctx?.drawImage(img, (img.width - size)/2, (img.height - size)/2, size, size, 0, 0, size, size); }; img.src = src; }; return (
{src && (
Original
)}
); }; // --- 4. Video Converter (MP4 to WebM via MediaRecorder) --- export const VideoConverter = () => { const videoRef = useRef(null); const [isProcessing, setIsProcessing] = useState(false); const [outputUrl, setOutputUrl] = useState(null); const handleFile = (e: React.ChangeEvent) => { const file = e.target.files?.[0]; if (file && videoRef.current) { videoRef.current.src = URL.createObjectURL(file); } }; const convert = () => { const video = videoRef.current; if (!video) return; setIsProcessing(true); const stream = (video as any).captureStream ? (video as any).captureStream() : (video as any).mozCaptureStream(); const mediaRecorder = new MediaRecorder(stream, { mimeType: 'video/webm' }); const chunks: BlobPart[] = []; mediaRecorder.ondataavailable = (e) => chunks.push(e.data); mediaRecorder.onstop = () => { const blob = new Blob(chunks, { type: 'video/webm' }); setOutputUrl(URL.createObjectURL(blob)); setIsProcessing(false); }; video.play(); mediaRecorder.start(); video.onended = () => { mediaRecorder.stop(); }; }; return (
); }; // --- 5. Audio Converter (Buffer to WAV) --- const writeWavHeader = (buffer: AudioBuffer) => { const numOfChan = buffer.numberOfChannels; const length = buffer.length * numOfChan * 2 + 44; const bufferArr = new ArrayBuffer(length); const view = new DataView(bufferArr); const channels = []; let i; let sample; let offset = 0; let pos = 0; // write WAVE header setUint32(0x46464952); // "RIFF" setUint32(length - 8); // file length - 8 setUint32(0x45564157); // "WAVE" setUint32(0x20746d66); // "fmt " chunk setUint32(16); // length = 16 setUint16(1); // PCM (uncompressed) setUint16(numOfChan); setUint32(buffer.sampleRate); setUint32(buffer.sampleRate * 2 * numOfChan); // avg. bytes/sec setUint16(numOfChan * 2); // block-align setUint16(16); // 16-bit (hardcoded in this example) setUint32(0x61746164); // "data" - chunk setUint32(length - pos - 4); // chunk length // write interleaved data for(i = 0; i < buffer.numberOfChannels; i++) channels.push(buffer.getChannelData(i)); while(pos < buffer.length) { for(i = 0; i < numOfChan; i++) { sample = Math.max(-1, Math.min(1, channels[i][pos])); // clamp sample = (0.5 + sample < 0 ? sample * 32768 : sample * 32767)|0; // scale to 16-bit signed int view.setInt16(offset, sample, true); offset += 2; } pos++; } return new Blob([bufferArr], { type: 'audio/wav' }); function setUint16(data: number) { view.setUint16(offset, data, true); offset += 2; } function setUint32(data: number) { view.setUint32(offset, data, true); offset += 4; } }; export const AudioConverter = () => { const [audioUrl, setAudioUrl] = useState(null); const handleFile = async (e: React.ChangeEvent) => { const file = e.target.files?.[0]; if(!file) return; const arrayBuffer = await file.arrayBuffer(); const audioCtx = new (window.AudioContext || (window as any).webkitAudioContext)(); const audioBuffer = await audioCtx.decodeAudioData(arrayBuffer); // Convert to WAV (simple implementation) const wavBlob = writeWavHeader(audioBuffer); setAudioUrl(URL.createObjectURL(wavBlob)); }; return (
{audioUrl && ( Download WAV )}
); }; // --- 6. Audio Trimmer --- export const AudioTrimmer = () => { const [buffer, setBuffer] = useState(null); const [start, setStart] = useState(0); const [end, setEnd] = useState(0); const [trimmedUrl, setTrimmedUrl] = useState(null); const handleFile = async (e: React.ChangeEvent) => { const file = e.target.files?.[0]; if(!file) return; const ctx = new AudioContext(); const ab = await file.arrayBuffer(); const decoded = await ctx.decodeAudioData(ab); setBuffer(decoded); setEnd(decoded.duration); }; const trim = () => { if(!buffer) return; const ctx = new AudioContext(); const duration = end - start; if(duration <= 0) return; const newBuffer = ctx.createBuffer(buffer.numberOfChannels, ctx.sampleRate * duration, ctx.sampleRate); for(let i=0; i {buffer && ( <>
setStart(Number(e.target.value))} />
setEnd(Number(e.target.value))} />

Duration: {buffer.duration.toFixed(2)}s

{trimmedUrl && ( Download Trimmed Audio )} )} ); }; // --- 7. Age Calculator --- export const AgeCalculator = () => { const [dob, setDob] = useState(''); const [result, setResult] = useState(''); const calculate = () => { if(!dob) return; const birth = new Date(dob); const now = new Date(); let years = now.getFullYear() - birth.getFullYear(); let months = now.getMonth() - birth.getMonth(); let days = now.getDate() - birth.getDate(); if (days < 0) { months--; days += new Date(now.getFullYear(), now.getMonth(), 0).getDate(); } if (months < 0) { years--; months += 12; } setResult(`${years} Years, ${months} Months, ${days} Days`); }; return (
setDob(e.target.value)} /> {result && {result}}
); }; // --- 8. EMI Calculator --- export const EmiCalculator = () => { const [p, setP] = useState(100000); const [r, setR] = useState(10); const [n, setN] = useState(12); const [emi, setEmi] = useState(null); const calc = () => { const monthlyRate = r / 12 / 100; const val = p * monthlyRate * Math.pow(1 + monthlyRate, n) / (Math.pow(1 + monthlyRate, n) - 1); setEmi(val); }; return (
setP(Number(e.target.value))} /> setR(Number(e.target.value))} /> setN(Number(e.target.value))} /> {emi && (

Monthly EMI: {emi.toFixed(2)}

Total Payment: {(emi * n).toFixed(2)}

)}
); }; // --- 9. SIP Calculator --- export const SipCalculator = () => { const [inv, setInv] = useState(5000); const [rate, setRate] = useState(12); const [years, setYears] = useState(10); const [res, setRes] = useState(null); const calc = () => { const i = rate / 100 / 12; const months = years * 12; const fv = inv * ((Math.pow(1 + i, months) - 1) / i) * (1 + i); setRes(fv); }; return (
setInv(Number(e.target.value))} /> setRate(Number(e.target.value))} /> setYears(Number(e.target.value))} /> {res && (

Invested: {inv * years * 12}

Future Value: {res.toFixed(2)}

)}
); }; // --- 10. QR Generator --- export const QrGenerator = () => { const [text, setText] = useState(''); const [qrUrl, setQrUrl] = useState(''); const generate = () => { if(!text) return; // Using a reliable public API for QR generation since we can't use complex libs setQrUrl(`https://api.qrserver.com/v1/create-qr-code/?size=150x150&data=${encodeURIComponent(text)}`); }; return (
setText(e.target.value)} /> {qrUrl && (
QR Code
)}
); }; // --- 11. Password Generator --- export const PasswordGenerator = () => { const [len, setLen] = useState(12); const [pass, setPass] = useState(''); const generate = () => { const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789!@#$%^&*()_+'; let res = ''; for(let i=0; i
setLen(Number(e.target.value))} className="accent-gold"/>
{pass && (
{pass}
)} ); }; // --- 12. Word Counter --- export const WordCounter = () => { const [text, setText] = useState(''); const stats = { chars: text.length, words: text.trim() === '' ? 0 : text.trim().split(/\s+/).length, sentences: text.split(/[.!?]+/).length - 1, }; return (