UNPKG

@lakshmiprasanth/react-voice-to-text

Version:

A modern React package for voice-to-text conversion with real-time speech recognition and file upload support

273 lines (247 loc) 12.4 kB
'use strict'; var jsxRuntime = require('react/jsx-runtime'); var react = require('react'); function getDefaultExportFromCjs (x) { return x && x.__esModule && Object.prototype.hasOwnProperty.call(x, 'default') ? x['default'] : x; } var classnames = {exports: {}}; /*! Copyright (c) 2018 Jed Watson. Licensed under the MIT License (MIT), see http://jedwatson.github.io/classnames */ (function (module) { /* global define */ (function () { var hasOwn = {}.hasOwnProperty; function classNames () { var classes = ''; for (var i = 0; i < arguments.length; i++) { var arg = arguments[i]; if (arg) { classes = appendClass(classes, parseValue(arg)); } } return classes; } function parseValue (arg) { if (typeof arg === 'string' || typeof arg === 'number') { return arg; } if (typeof arg !== 'object') { return ''; } if (Array.isArray(arg)) { return classNames.apply(null, arg); } if (arg.toString !== Object.prototype.toString && !arg.toString.toString().includes('[native code]')) { return arg.toString(); } var classes = ''; for (var key in arg) { if (hasOwn.call(arg, key) && arg[key]) { classes = appendClass(classes, key); } } return classes; } function appendClass (value, newClass) { if (!newClass) { return value; } if (value) { return value + ' ' + newClass; } return value + newClass; } if (module.exports) { classNames.default = classNames; module.exports = classNames; } else { window.classNames = classNames; } }()); } (classnames)); var classnamesExports = classnames.exports; var classNames = /*@__PURE__*/getDefaultExportFromCjs(classnamesExports); const SUPPORTED_LANGUAGES = [ { code: 'en-US', name: 'English (US)' }, { code: 'en-GB', name: 'English (UK)' }, { code: 'es-ES', name: 'Spanish' }, { code: 'fr-FR', name: 'French' }, { code: 'de-DE', name: 'German' }, { code: 'it-IT', name: 'Italian' }, { code: 'pt-BR', name: 'Portuguese (Brazil)' }, { code: 'ja-JP', name: 'Japanese' }, { code: 'ko-KR', name: 'Korean' }, { code: 'zh-CN', name: 'Chinese (Simplified)' }, { code: 'zh-TW', name: 'Chinese (Traditional)' }, { code: 'ru-RU', name: 'Russian' }, { code: 'ar-SA', name: 'Arabic' }, { code: 'hi-IN', name: 'Hindi' }, { code: 'th-TH', name: 'Thai' }, { code: 'vi-VN', name: 'Vietnamese' }, { code: 'tr-TR', name: 'Turkish' }, { code: 'pl-PL', name: 'Polish' }, { code: 'nl-NL', name: 'Dutch' }, { code: 'sv-SE', name: 'Swedish' }, { code: 'da-DK', name: 'Danish' }, { code: 'no-NO', name: 'Norwegian' }, { code: 'fi-FI', name: 'Finnish' }, { code: 'cs-CZ', name: 'Czech' }, { code: 'hu-HU', name: 'Hungarian' }, { code: 'ro-RO', name: 'Romanian' }, { code: 'bg-BG', name: 'Bulgarian' }, { code: 'hr-HR', name: 'Croatian' }, { code: 'sk-SK', name: 'Slovak' }, { code: 'sl-SI', name: 'Slovenian' }, { code: 'et-EE', name: 'Estonian' }, { code: 'lv-LV', name: 'Latvian' }, { code: 'lt-LT', name: 'Lithuanian' }, { code: 'mt-MT', name: 'Maltese' }, { code: 'el-GR', name: 'Greek' }, { code: 'he-IL', name: 'Hebrew' }, { code: 'id-ID', name: 'Indonesian' }, { code: 'ms-MY', name: 'Malay' }, { code: 'fil-PH', name: 'Filipino' }, { code: 'uk-UA', name: 'Ukrainian' }, { code: 'be-BY', name: 'Belarusian' }, { code: 'kk-KZ', name: 'Kazakh' }, { code: 'ky-KG', name: 'Kyrgyz' }, { code: 'uz-UZ', name: 'Uzbek' }, { code: 'mn-MN', name: 'Mongolian' }, { code: 'ka-GE', name: 'Georgian' }, { code: 'hy-AM', name: 'Armenian' }, { code: 'az-AZ', name: 'Azerbaijani' }, { code: 'fa-IR', name: 'Persian' }, { code: 'ur-PK', name: 'Urdu' }, { code: 'bn-BD', name: 'Bengali' }, { code: 'si-LK', name: 'Sinhala' }, { code: 'my-MM', name: 'Burmese' }, { code: 'km-KH', name: 'Khmer' }, { code: 'lo-LA', name: 'Lao' }, { code: 'ne-NP', name: 'Nepali' }, { code: 'gu-IN', name: 'Gujarati' }, { code: 'pa-IN', name: 'Punjabi' }, { code: 'te-IN', name: 'Telugu' }, { code: 'kn-IN', name: 'Kannada' }, { code: 'ml-IN', name: 'Malayalam' }, { code: 'ta-IN', name: 'Tamil' }, { code: 'mr-IN', name: 'Marathi' }, { code: 'or-IN', name: 'Odia' }, { code: 'as-IN', name: 'Assamese' }, { code: 'sa-IN', name: 'Sanskrit' }, { code: 'am-ET', name: 'Amharic' }, { code: 'sw-KE', name: 'Swahili' }, { code: 'yo-NG', name: 'Yoruba' }, { code: 'ig-NG', name: 'Igbo' }, { code: 'ha-NG', name: 'Hausa' }, { code: 'zu-ZA', name: 'Zulu' }, { code: 'af-ZA', name: 'Afrikaans' }, { code: 'xh-ZA', name: 'Xhosa' }, { code: 'st-ZA', name: 'Southern Sotho' }, { code: 'tn-ZA', name: 'Tswana' }, { code: 'ss-ZA', name: 'Swati' }, { code: 've-ZA', name: 'Venda' }, { code: 'ts-ZA', name: 'Tsonga' }, { code: 'nr-ZA', name: 'Southern Ndebele' }, { code: 'nd-ZA', name: 'Northern Ndebele' } ]; const LanguageSelector = ({ value = 'en-US', onChange, disabled = false, className, showLabel = true, label = 'Language', placeholder = 'Select language...', ...props }) => { const handleChange = (event) => { onChange?.(event.target.value); }; return (jsxRuntime.jsxs("div", { className: classNames('language-selector', className), ...props, children: [showLabel && (jsxRuntime.jsx("label", { className: "language-selector__label", children: label })), jsxRuntime.jsxs("select", { value: value, onChange: handleChange, disabled: disabled, className: "language-selector__select", children: [jsxRuntime.jsx("option", { value: "", disabled: true, children: placeholder }), SUPPORTED_LANGUAGES.map((language) => (jsxRuntime.jsx("option", { value: language.code, children: language.name }, language.code)))] })] })); }; const FileUpload = ({ className, onFileSelect, onConvert, onError, acceptedFormats = ['audio/*'], maxFileSize = 50 * 1024 * 1024, // 50MB showLanguageSelector = true, language = 'en-US', dragAndDrop = true, multiple = false, disabled = false, children, ...props }) => { const [selectedFile, setSelectedFile] = react.useState(null); const [isConverting, setIsConverting] = react.useState(false); const [isDragOver, setIsDragOver] = react.useState(false); const [selectedLanguage, setSelectedLanguage] = react.useState(language); const fileInputRef = react.useRef(null); const handleFileSelect = (file) => { // Validate file size if (file.size > maxFileSize) { const error = `File size (${(file.size / 1024 / 1024).toFixed(2)}MB) exceeds maximum allowed size (${(maxFileSize / 1024 / 1024).toFixed(2)}MB)`; onError?.(error); return; } // Validate file type const isValidType = acceptedFormats.some(format => { if (format === 'audio/*') { return file.type.startsWith('audio/'); } return file.type === format; }); if (!isValidType) { const error = `File type ${file.type} is not supported. Please select an audio file.`; onError?.(error); return; } setSelectedFile(file); onFileSelect?.(file); }; const handleFileInputChange = (event) => { const files = event.target.files; if (files && files.length > 0) { handleFileSelect(files[0]); } }; const handleDragOver = (event) => { event.preventDefault(); setIsDragOver(true); }; const handleDragLeave = (event) => { event.preventDefault(); setIsDragOver(false); }; const handleDrop = (event) => { event.preventDefault(); setIsDragOver(false); const files = event.dataTransfer.files; if (files && files.length > 0) { handleFileSelect(files[0]); } }; const handleConvert = async () => { if (!selectedFile) return; setIsConverting(true); try { await onConvert?.(selectedFile, selectedLanguage); } catch (error) { onError?.(error instanceof Error ? error.message : 'Failed to convert file'); } finally { setIsConverting(false); } }; const handleClearFile = () => { setSelectedFile(null); if (fileInputRef.current) { fileInputRef.current.value = ''; } }; const handleLanguageChange = (newLanguage) => { setSelectedLanguage(newLanguage); }; const openFileDialog = () => { fileInputRef.current?.click(); }; const formatFileSize = (bytes) => { if (bytes === 0) return '0 Bytes'; const k = 1024; const sizes = ['Bytes', 'KB', 'MB', 'GB']; const i = Math.floor(Math.log(bytes) / Math.log(k)); return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i]; }; return (jsxRuntime.jsxs("div", { className: classNames('file-upload', className), ...props, children: [jsxRuntime.jsxs("div", { className: "file-upload__header", children: [jsxRuntime.jsx("h3", { children: "\uD83D\uDCC1 File Upload & Convert" }), jsxRuntime.jsx("p", { children: "Upload an audio file to convert speech to text" })] }), jsxRuntime.jsxs("div", { className: "file-upload__content", children: [showLanguageSelector && (jsxRuntime.jsx("div", { className: "file-upload__language", children: jsxRuntime.jsx(LanguageSelector, { value: selectedLanguage, onChange: handleLanguageChange, disabled: disabled || isConverting }) })), jsxRuntime.jsxs("div", { className: "file-upload__upload-area", children: [dragAndDrop ? (jsxRuntime.jsx("div", { className: classNames('file-upload__drop-zone', { 'file-upload__drop-zone--drag-over': isDragOver, 'file-upload__drop-zone--disabled': disabled }), onDragOver: handleDragOver, onDragLeave: handleDragLeave, onDrop: handleDrop, onClick: !disabled ? openFileDialog : undefined, children: jsxRuntime.jsxs("div", { className: "file-upload__drop-zone-content", children: [jsxRuntime.jsx("div", { className: "file-upload__icon", children: "\uD83D\uDCC1" }), jsxRuntime.jsx("p", { className: "file-upload__drop-text", children: isDragOver ? 'Drop your audio file here' : 'Click to select or drag & drop audio file' }), jsxRuntime.jsx("p", { className: "file-upload__drop-hint", children: "Supported formats: MP3, WAV, OGG, FLAC, M4A" }), jsxRuntime.jsxs("p", { className: "file-upload__drop-hint", children: ["Max size: ", formatFileSize(maxFileSize)] })] }) })) : (jsxRuntime.jsxs("div", { className: "file-upload__input-wrapper", children: [jsxRuntime.jsx("input", { ref: fileInputRef, type: "file", accept: acceptedFormats.join(','), onChange: handleFileInputChange, disabled: disabled, multiple: multiple, className: "file-upload__input" }), jsxRuntime.jsx("button", { onClick: openFileDialog, disabled: disabled, className: "file-upload__select-button", children: "Select Audio File" })] })), jsxRuntime.jsx("input", { ref: fileInputRef, type: "file", accept: acceptedFormats.join(','), onChange: handleFileInputChange, disabled: disabled, multiple: multiple, className: "file-upload__hidden-input" })] }), selectedFile && (jsxRuntime.jsxs("div", { className: "file-upload__file-info", children: [jsxRuntime.jsxs("div", { className: "file-upload__file-details", children: [jsxRuntime.jsx("div", { className: "file-upload__file-name", children: selectedFile.name }), jsxRuntime.jsx("div", { className: "file-upload__file-size", children: formatFileSize(selectedFile.size) })] }), jsxRuntime.jsx("button", { onClick: handleClearFile, disabled: isConverting, className: "file-upload__clear-button", children: "\u2715" })] })), jsxRuntime.jsx("div", { className: "file-upload__controls", children: jsxRuntime.jsx("button", { onClick: handleConvert, disabled: !selectedFile || disabled || isConverting, className: "file-upload__convert-button", children: isConverting ? '🔄 Converting...' : '🔄 Convert File' }) }), children && (jsxRuntime.jsx("div", { className: "file-upload__children", children: children }))] })] })); }; exports.FileUpload = FileUpload; //# sourceMappingURL=FileUpload.js.map