UNPKG

vlibras-player-webjs

Version:

Biblioteca JavaScript moderna para integração do VLibras Player com React, Vue, Angular e vanilla JS

382 lines 12.7 kB
"use strict"; /** * Sistema de Plugins Extensível para VLibras * Permite extensão da funcionalidade base através de plugins */ Object.defineProperty(exports, "__esModule", { value: true }); exports.VLibrasPlugins = exports.vlibrasPluginManager = exports.PerformancePlugin = exports.AccessibilityPlugin = exports.AnalyticsPlugin = exports.VLibrasPluginManager = void 0; /** * Event emitter simplificado para plugins */ class SimpleEventEmitter { constructor() { this.events = new Map(); } emit(event, data) { const listeners = this.events.get(event) || []; listeners.forEach(listener => { try { listener(data); } catch (error) { console.error(`Erro em listener do evento ${event}:`, error); } }); } on(event, callback) { if (!this.events.has(event)) { this.events.set(event, []); } this.events.get(event).push(callback); } off(event, callback) { const listeners = this.events.get(event); if (listeners) { const index = listeners.indexOf(callback); if (index > -1) { listeners.splice(index, 1); } } } } /** * Gerenciador de plugins do VLibras */ class VLibrasPluginManager { constructor() { this.plugins = new Map(); this.eventEmitter = new SimpleEventEmitter(); } static getInstance() { if (!VLibrasPluginManager.instance) { VLibrasPluginManager.instance = new VLibrasPluginManager(); } return VLibrasPluginManager.instance; } /** * Registra um plugin */ async register(plugin, config) { const validation = this.validatePlugin(plugin); if (!validation.valid) { throw new Error(`Plugin inválido: ${validation.errors.join(', ')}`); } // Verificar dependências await this.checkDependencies(plugin); const info = { plugin, config, active: false, errorCount: 0 }; this.plugins.set(plugin.name, info); this.eventEmitter.emit('plugin:registered', { name: plugin.name, version: plugin.version }); console.log(`✅ Plugin '${plugin.name}' registrado com sucesso`); } /** * Ativa um plugin para um player específico */ async activate(pluginName, player) { const info = this.plugins.get(pluginName); if (!info) { throw new Error(`Plugin '${pluginName}' não encontrado`); } if (info.active) { console.warn(`Plugin '${pluginName}' já está ativo`); return; } try { const startTime = performance.now(); await info.plugin.setup(player, info.config); const setupTime = performance.now() - startTime; info.setupTime = setupTime; info.active = true; // Registrar hooks do ciclo de vida if (info.plugin.onPlayerReady) { player.on('player:ready', () => info.plugin.onPlayerReady(player)); } if (info.plugin.onTranslation) { player.on('translation:start', ({ text }) => info.plugin.onTranslation(text, player)); } if (info.plugin.onError) { player.on('player:error', ({ error }) => info.plugin.onError(error, player)); } this.eventEmitter.emit('plugin:activated', { name: pluginName, setupTime }); console.log(`🚀 Plugin '${pluginName}' ativado (${setupTime.toFixed(2)}ms)`); } catch (error) { info.errorCount++; info.lastError = error; this.eventEmitter.emit('plugin:error', { name: pluginName, error }); throw new Error(`Erro ao ativar plugin '${pluginName}': ${error.message}`); } } /** * Desativa um plugin */ async deactivate(pluginName, player) { const info = this.plugins.get(pluginName); if (!info) { throw new Error(`Plugin '${pluginName}' não encontrado`); } if (!info.active) { console.warn(`Plugin '${pluginName}' já está inativo`); return; } try { if (info.plugin.teardown) { await info.plugin.teardown(player); } info.active = false; this.eventEmitter.emit('plugin:deactivated', { name: pluginName }); console.log(`🛑 Plugin '${pluginName}' desativado`); } catch (error) { info.errorCount++; info.lastError = error; throw new Error(`Erro ao desativar plugin '${pluginName}': ${error.message}`); } } /** * Lista plugins registrados */ list() { return Array.from(this.plugins.values()); } /** * Lista plugins por categoria */ listByCategory(category) { return this.list().filter(info => info.plugin.category === category); } /** * Obtém informações de um plugin específico */ getPluginInfo(name) { return this.plugins.get(name); } /** * Valida um plugin */ validatePlugin(plugin) { const errors = []; const warnings = []; // Validações obrigatórias if (!plugin.name || plugin.name.trim() === '') { errors.push('Nome do plugin é obrigatório'); } if (!plugin.version || plugin.version.trim() === '') { errors.push('Versão do plugin é obrigatória'); } if (typeof plugin.setup !== 'function') { errors.push('Método setup é obrigatório'); } // Validações de boas práticas if (!plugin.description) { warnings.push('Descrição do plugin é recomendada'); } if (!plugin.category) { warnings.push('Categoria do plugin é recomendada'); } // Verificar se já existe plugin com mesmo nome if (this.plugins.has(plugin.name)) { errors.push(`Já existe plugin com nome '${plugin.name}'`); } return { valid: errors.length === 0, errors, warnings }; } /** * Verifica dependências do plugin */ async checkDependencies(plugin) { if (!plugin.dependencies || plugin.dependencies.length === 0) { return; } const missingDeps = []; for (const dep of plugin.dependencies) { if (!this.plugins.has(dep)) { missingDeps.push(dep); } } if (missingDeps.length > 0) { throw new Error(`Dependências não encontradas para plugin '${plugin.name}': ${missingDeps.join(', ')}`); } } /** * Ativa plugins automaticamente baseado em configuração */ async autoActivate(player, config = {}) { const { enabledPlugins = [] } = config; for (const pluginName of enabledPlugins) { try { await this.activate(pluginName, player); } catch (error) { console.error(`Erro ao ativar plugin '${pluginName}':`, error.message); } } } /** * Obtém estatísticas dos plugins */ getStats() { const plugins = this.list(); return { total: plugins.length, active: plugins.filter(p => p.active).length, inactive: plugins.filter(p => !p.active).length, withErrors: plugins.filter(p => p.errorCount > 0).length, byCategory: plugins.reduce((acc, p) => { const cat = p.plugin.category || 'unknown'; acc[cat] = (acc[cat] || 0) + 1; return acc; }, {}), avgSetupTime: plugins .filter(p => p.setupTime) .reduce((sum, p, _, arr) => sum + (p.setupTime / arr.length), 0) }; } /** * Adiciona listener para eventos de plugins */ on(event, callback) { this.eventEmitter.on(event, callback); } /** * Remove todos os plugins */ clear() { this.plugins.clear(); } } exports.VLibrasPluginManager = VLibrasPluginManager; VLibrasPluginManager.instance = null; // Plugin pré-construídos como exemplos /** * Plugin de Analytics simples */ exports.AnalyticsPlugin = { name: 'analytics', version: '1.0.0', description: 'Plugin básico para coleta de métricas de uso', category: 'analytics', setup(player, config = {}) { console.log('📊 Analytics Plugin ativado', config.trackingId); player.on('translation:start', ({ text }) => { console.log('📈 Analytics: Tradução iniciada', { text: text.substring(0, 50) }); }); player.on('animation:complete', ({ duration }) => { console.log('📈 Analytics: Animação concluída', { duration }); }); }, teardown() { console.log('📊 Analytics Plugin desativado'); } }; /** * Plugin de Accessibility */ function announceMessage(message) { // Criar elemento para leitores de tela const announcer = document.createElement('div'); announcer.setAttribute('aria-live', 'polite'); announcer.setAttribute('aria-atomic', 'true'); announcer.style.position = 'absolute'; announcer.style.left = '-10000px'; announcer.textContent = message; document.body.appendChild(announcer); setTimeout(() => { if (document.body.contains(announcer)) { document.body.removeChild(announcer); } }, 1000); } exports.AccessibilityPlugin = { name: 'accessibility', version: '1.0.0', description: 'Plugin para melhorias de acessibilidade', category: 'accessibility', setup(player, config = {}) { if (config.announceChanges) { player.on('player:ready', () => { announceMessage('VLibras player pronto para uso'); }); player.on('translation:start', ({ text }) => { announceMessage(`Iniciando tradução: ${text.substring(0, 100)}`); }); } } }; /** * Plugin de Performance Monitor */ exports.PerformancePlugin = { name: 'performance-monitor', version: '1.0.0', description: 'Monitor de performance em tempo real', category: 'performance', setup(player) { const performanceData = []; player.on('translation:start', ({ timestamp }) => { performanceData.push({ type: 'translation_start', timestamp, memoryUsage: performance.memory?.usedJSHeapSize || 0 }); }); player.on('animation:complete', ({ duration }) => { performanceData.push({ type: 'animation_complete', duration, memoryUsage: performance.memory?.usedJSHeapSize || 0 }); // Log se animação demorou muito if (duration > 5000) { console.warn('⚠️ Animação lenta detectada:', duration, 'ms'); } }); // Adicionar método para obter relatório this.getPerformanceReport = () => { return { totalEvents: performanceData.length, avgMemoryUsage: performanceData.reduce((sum, d) => sum + (d.memoryUsage / performanceData.length), 0), slowAnimations: performanceData .filter((d) => d.type === 'animation_complete' && d.duration > 3000) .length }; }; } }; /** * Instância singleton do gerenciador */ exports.vlibrasPluginManager = VLibrasPluginManager.getInstance(); /** * API simplificada para uso direto */ exports.VLibrasPlugins = { register: (plugin, config) => exports.vlibrasPluginManager.register(plugin, config), activate: (name, player) => exports.vlibrasPluginManager.activate(name, player), deactivate: (name, player) => exports.vlibrasPluginManager.deactivate(name, player), list: () => exports.vlibrasPluginManager.list(), stats: () => exports.vlibrasPluginManager.getStats(), // Plugins pré-construídos builtIn: { analytics: exports.AnalyticsPlugin, accessibility: exports.AccessibilityPlugin, performance: exports.PerformancePlugin } }; //# sourceMappingURL=VLibrasPlugins.js.map