UNPKG

vlibras-player-nextjs

Version:

VLibras Player para Next.js - Biblioteca moderna para tradução de texto em Libras com callbacks de estado

1,015 lines (808 loc) 30.1 kB
# vlibras-player-nextjs > Biblioteca moderna do VLibras Player para Next.js e React com TypeScript ![Version](https://img.shields.io/badge/version-v2.4.1-blue.svg) ![License](https://img.shields.io/badge/license-LGPLv3-blue.svg) ![TypeScript](https://img.shields.io/badge/TypeScript-Ready-blue.svg) ![Next.js](https://img.shields.io/badge/Next.js-13+-black.svg) ![React](https://img.shields.io/badge/React-18+-blue.svg) ![NPM Downloads](https://img.shields.io/npm/dm/vlibras-player-nextjs) ## 🎯 Sobre O **vlibras-player-nextjs** é uma biblioteca moderna e otimizada do VLibras Player, especialmente desenvolvida para aplicações Next.js e React. Esta biblioteca permite integrar facilmente a tradução automática de texto para Libras (Língua Brasileira de Sinais) em suas aplicações web. ### ✨ Principais Características - 🚀 **Compatível com Next.js 13+** (App Router e Pages Router) - 🔷 **TypeScript nativo** com tipagem completa - ⚛️ **Hooks React modernos** com conexão automática ao DOM - 🎨 **Componentes estilizados** prontos para uso - 📱 **Design responsivo** e acessível - 🌙 **Suporte a tema escuro** - 🔧 **API moderna** e fácil de usar - 📦 **Tree-shaking** otimizado - 🧪 **Totalmente testado** - 🔄 **Conexão automática** ao container DOM (v2.1.0+) - 🔧 **Sem duplicação** de containers Unity (v2.1.1+) - 🎯 **Callbacks de estado** para monitoramento preciso (v2.2.0+) - 🔄 **Gerenciamento Unity corrigido** com aguardo real de prontidão (v2.3.0+) ## 🆕 Novidades v2.5.0 - Hook com Melhores Práticas React! ⚛️ A versão **v2.5.0** traz o **hook redesenhado seguindo as melhores práticas do React**: ### 🏗️ Arquitetura Moderna com useReducer -**Estado Centralizado**: Gerenciamento com `useReducer` para maior previsibilidade -**Memoização Inteligente**: Callbacks e objetos memoizados para performance otimizada -**Estados Derivados**: `canTranslate`, `canPause`, `canResume`, `canStop`, `canRestart` -**Tratamento de Erros Robusto**: Distinção entre erros fatais e avisos -**Debouncing**: Prevenção de traduções muito rápidas consecutivas ### 🎯 Interface Organizadas em Grupos ```tsx const player = useVLibrasPlayer({ containerRef, autoInit: true }); // Controles agrupados player.controls.play(); player.controls.pause(); // Configurações agrupadas player.settings.setSpeed(1.5); player.settings.setRegion('BR'); // Utilitários agrupados player.utils.clearWarnings(); player.utils.retry(); ``` ### 🚀 Funcionalidades Avançadas -**Retry Automático**: Tentativas de reconexão configuráveis - ⏱️ **Debouncing**: Controle de frequência de traduções - 🛑 **AbortController**: Cancelamento de operações assíncronas - 🧹 **Cleanup Automático**: Gerenciamento de memória e timers -**Estados Derivados**: Estados computados para UX melhor ### 🔗 Compatibilidade Mantida -**API Legacy**: Métodos antigos mantidos para compatibilidade -**Migração Gradual**: Adote novas práticas progressivamente -**TypeScript Melhorado**: Tipagem mais precisa e documentação inline ### ⚠️ Principais Melhorias v2.4.1: 1. **Hook incompleto sem novas funcionalidades** → ✅ **Hook oficial 100% atualizado** 2. **Faltavam controles inteligentes** → ✅ **Controles automáticos baseados no estado** 3. **Sem logging de eventos** → ✅ **Sistema completo de event logging** 4. **Callbacks não integrados no hook** → ✅ **Integração total com callbacks** 5. **Erros de tipagem TypeScript** → ✅ **Tipos corrigidos e interface atualizada** ## 🆕 v2.3.0 - Correções Críticas de Estado A versão **v2.3.0** corrige **problemas críticos** de gerenciamento de estado Unity: -**UnityStateManager**: Nova classe para controle preciso do estado Unity WebGL -**Aguardo de Prontidão**: Métodos aguardam automaticamente Unity estar pronto -**Callbacks Funcionais**: Sistema de callbacks totalmente corrigido -**Detecção de Animação**: Aguarda conclusão real das animações -**Estados Confiáveis**: `isReady` reflete o estado real do Unity -**Debugging**: Informações detalhadas para desenvolvimento ### ⚠️ Problemas Corrigidos na v2.3.0: 1. **`isReady: true` antes do Unity estar pronto** → ✅ Corrigido 2. **Callbacks `onLoad` não funcionando** → ✅ Corrigido 3. **Tradução não aguardando animação** → ✅ Corrigido 4. **Estados inconsistentes** → ✅ Corrigido ## 🆕 v2.2.0 - Callbacks de Estado (Base) A versão **v2.2.0** introduz **callbacks de estado** que permitem monitorar eventos reais do VLibras Player: ```typescript const { translate, isTranslating, isPlaying } = useVLibrasPlayer({ // ✅ Callbacks de tradução onTranslationStart: () => console.log('🎬 Tradução iniciada'), onTranslationEnd: () => console.log('✅ Tradução finalizada'), onTranslationError: (error) => console.log('❌ Erro:', error), // ✅ Callbacks de reprodução onPlay: () => console.log('▶️ Reprodução iniciada'), onPause: () => console.log('⏸️ Pausado'), onStop: () => console.log('⏹️ Parado'), // ✅ Callbacks do player onPlayerReady: () => console.log('🚀 Player pronto'), onPlayerError: (error) => console.log('💥 Erro no player:', error), }); // ✅ Estados precisos baseados em eventos reais console.log('Traduzindo:', isTranslating); // true/false preciso console.log('Reproduzindo:', isPlaying); // true/false preciso ``` **Benefícios dos Callbacks:** - 🎯 **Estado preciso** - Conhecimento real do que está acontecendo - 🖥️ **UI responsiva** - Interfaces que refletem o estado real - 📊 **Analytics** - Logging preciso de eventos - 🔄 **Sem timers** - Eventos nativos do Unity WebGL -**Retrocompatível** - API anterior continua funcionando > 📚 **Documentação completa:** [docs/CALLBACKS_DOCUMENTATION.md](docs/CALLBACKS_DOCUMENTATION.md) ## 📦 Instalação ```bash npm install vlibras-player-nextjs # ou yarn add vlibras-player-nextjs # ou pnpm add vlibras-player-nextjs ``` ## � Debugging e Estado Unity (v2.3.0) Para verificar o estado real do Unity e debugar problemas: ```tsx 'use client'; import { useVLibrasPlayer, UnityStateManager } from 'vlibras-player-nextjs'; export default function DebugComponent() { const { player, isReady, connect } = useVLibrasPlayer({ onLoad: () => console.log('✅ Unity realmente pronto!'), }); const showDebugInfo = () => { const debugInfo = UnityStateManager.getDebugInfo(); console.log('🔍 Debug Unity:', debugInfo); // Verificação manual do estado console.log('🔍 Unity Ready:', UnityStateManager.isUnityReady()); console.log('🔍 Animation Playing:', UnityStateManager.isAnimationPlaying()); }; return ( <div> <button onClick={showDebugInfo}>Ver Debug Info</button> <div id="vlibras-player-container"></div> <div>Estado: {isReady ? '✅ Pronto' : '⏳ Carregando'}</div> </div> ); } ``` ## �🚀 Uso Básico ### Hook React Moderno (v2.5.0+) ⚛️ ```typescript 'use client'; import { useRef } from 'react'; import { useVLibrasPlayer } from 'vlibras-player-nextjs'; export default function ModernVLibrasComponent() { const containerRef = useRef<HTMLDivElement>(null); // 🚀 Hook com melhores práticas React const player = useVLibrasPlayer({ containerRef, autoInit: true, retryOnError: true, maxRetries: 3, debounceMs: 300, // Callbacks organizados onPlayerReady: () => console.log('🚀 Player pronto!'), onStateChange: (state) => console.log('📊 Estado:', state.status), onTranslationStart: () => console.log('🎬 Tradução iniciada'), onTranslationEnd: () => console.log('✅ Tradução finalizada'), onPlayerError: (error, isFatal) => { console.log(isFatal ? '💥 Erro fatal:' : '⚠️ Aviso:', error); } }); const handleTranslate = async () => { if (!player.canTranslate) return; try { await player.translate("Olá mundo moderno!"); } catch (error) { console.error('Erro na tradução:', error); } }; return ( <div> <div ref={containerRef} className="vlibras-container" /> {/* Controles inteligentes baseados em estado derivado */} <button onClick={handleTranslate} disabled={!player.canTranslate} > {player.isBusy ? 'Processando...' : 'Traduzir'} </button> <button onClick={player.controls.pause} disabled={!player.canPause} > Pausar </button> <button onClick={player.controls.resume} disabled={!player.canResume} > Retomar </button> <button onClick={player.controls.stop} disabled={!player.canStop} > Parar </button> {/* Configurações */} <button onClick={() => player.settings.setSpeed(1.5)}> Velocidade 1.5x </button> {/* Utilitários */} {player.hasWarnings && ( <button onClick={player.utils.clearWarnings}> Limpar Avisos ({player.errors.warnings.length}) </button> )} {/* Estado visual */} <div> <p>Status: {player.status}</p> <p>Pronto: {player.isReady ? '✅' : '⏳'}</p> <p>Traduzindo: {player.isTranslating ? '🎬' : '⏸️'}</p> <p>Reproduzindo: {player.isPlaying ? '▶️' : '⏹️'}</p> {player.errors.fatal && ( <p style={{ color: 'red' }}>Erro: {player.errors.fatal}</p> )} </div> </div> ); } ``` ### API de Compatibilidade (v2.4.x e anteriores) ```typescript 'use client'; import { useRef } from 'react'; import { useVLibrasPlayer } from 'vlibras-player-nextjs'; export default function LegacyComponent() { const containerRef = useRef<HTMLDivElement>(null); const { translate, isReady, isLoading, error } = useVLibrasPlayer({ autoInit: true, containerRef, // 🔥 CONEXÃO AUTOMÁTICA! targetPath: '/vlibras/target', region: 'BR', onLoad: () => console.log('Player carregado!'), onError: (error) => console.error('Erro:', error) }); const handleTranslate = async () => { if (!isReady) return; try { await translate("Olá mundo!"); } catch (error) { console.error('Erro na tradução:', error); } }; return ( <div> <div ref={containerRef} className="vlibras-container" /> <button onClick={handleTranslate} disabled={!isReady || isLoading} > {isLoading ? 'Traduzindo...' : 'Traduzir'} </button> {error && <p style={{ color: 'red' }}>Erro: {error}</p>} </div> ); } } ``` ### Classe VLibras Player (Uso Direto) ```typescript 'use client'; import { VLibrasPlayer } from 'vlibras-player-nextjs'; import { useRef, useEffect, useState } from 'react'; export default function DirectUsage() { const containerRef = useRef<HTMLDivElement>(null); const [player, setPlayer] = useState<VLibrasPlayer | null>(null); const [isLoading, setIsLoading] = useState(false); useEffect(() => { if (containerRef.current) { const playerInstance = new VLibrasPlayer({ targetPath: '/vlibras/target', region: 'BR' }); playerInstance.load(containerRef.current); setPlayer(playerInstance); } }, []); const handleTranslate = async () => { if (!player) return; setIsLoading(true); try { await player.translate("Olá mundo!"); } catch (error) { console.error('Erro na tradução:', error); } finally { setIsLoading(false); } }; return ( <div> <div ref={containerRef} className="vlibras-container" /> <button onClick={handleTranslate} disabled={!player || isLoading}> {isLoading ? 'Traduzindo...' : 'Traduzir'} </button> </div> ); } ``` player.load(containerRef.current); } }, [player]); ## 🆕 Novidades da v2.1.1 ### 🔧 Bug Crítico de Duplicação Resolvido A v2.1.1 resolve um **bug crítico** que causava duplicação de containers Unity WebGL: #### ❌ Problema (v2.1.0 e anteriores) - 🔴 **Múltiplos containers**: Criava containers duplicados a cada re-render - 🔴 **Vazamentos de memória**: Containers órfãos não eram limpos - 🔴 **Performance degradada**: Múltiplas instâncias Unity simultâneas - 🔴 **IDs aleatórios**: Timestamps únicos impediam reutilização #### ✅ Solução (v2.1.1) - 🟢 **Container único**: Reutiliza container existente quando possível - 🟢 **Cleanup automático**: Remove containers órfãos antes de criar novos - 🟢 **IDs estáveis**: Baseados na região em vez de timestamps - 🟢 **Verificação de estado**: Só carrega Unity se necessário ### 🚀 Melhorias Implementadas 1. **Verificação de Container Existente**: Player reutiliza containers quando possível 2. **Cleanup Automático**: Remove containers órfãos para evitar duplicação 3. **IDs Estáveis**: Containers têm IDs previsíveis para melhor reutilização 4. **Dispose Melhorado**: Limpeza completa de estado e recursos 5. **Hook Otimizado**: Dependências otimizadas para evitar re-execuções ## 🔄 Novidades da v2.1.0 ### ✅ Hook useVLibrasPlayer Corrigido O principal problema da v2.0.0 foi resolvido! Agora o hook **conecta automaticamente** ao container DOM: #### ❌ Antes (v2.0.0 - Quebrado) ```typescript const { player, translate } = useVLibrasPlayer({ autoInit: true }); // ❌ Necessário fazer conexão manual useEffect(() => { if (containerRef.current && player) { player.load(containerRef.current); // ❌ Não funcionava } }, [player]); ``` #### ✅ Agora (v2.1.0+ - Funciona!) ```typescript const { translate, isReady } = useVLibrasPlayer({ autoInit: true, containerRef // ✅ Conexão automática! }); // ✅ Pronto para usar, sem configuração adicional! ``` ### 🚀 Funcionalidades v2.1.0 1. **Conexão Automática**: Use `containerRef` para conexão automática 2. **Callbacks de Eventos**: `onLoad`, `onTranslateStart`, `onTranslateEnd`, `onError` 3. **Estado `isReady`**: Saiba quando o player está pronto para uso 4. **Método `connect()`**: Conexão manual quando necessário 5. **Tratamento de Erros Melhorado**: Erros mais informativos if (playerRef.current) { await playerRef.current.translate('Olá mundo!'); } }; return ( <div> <div ref={containerRef} className="vlibras-container" /> <button onClick={handleTranslate}>Traduzir</button> </div> ); } </button> <button onClick={() => play()}>Play</button> <button onClick={() => pause()}>Pause</button> </div> <div className="status"> Status: {player.status} | Carregado: {player.loaded ? 'Sim' : 'Não'} </div> </div> ); } ``` ## 🔧 API Completa ### Hook useVLibrasPlayer (v2.1.0+) ```typescript interface UseVLibrasPlayerOptions { // Configurações do Player autoInit?: boolean; // Inicializa automaticamente containerRef?: RefObject<HTMLElement>; // Ref para conexão automática targetPath?: string; // Caminho dos arquivos Unity translatorUrl?: string; // URL do serviço de tradução region?: 'BR' | 'PT'; // Região do dicionário enableStats?: boolean; // Habilitar estatísticas // Callbacks onLoad?: () => void; // Player carregado onTranslateStart?: (text: string) => void; // Tradução iniciada onTranslateEnd?: (gloss: string) => void; // Tradução finalizada onError?: (error: string) => void; // Erro ocorrido } // Uso do Hook const { // Estado player, // Estado atual do player isLoading, // Se está carregando/traduzindo error, // Erro atual (se houver) isReady, // Se está pronto para uso (v2.1.0+) // Métodos de Controle translate, // Traduzir texto play, // Reproduzir animação pause, // Pausar animação stop, // Parar animação repeat, // Repetir última animação setSpeed, // Definir velocidade toggleSubtitle, // Alternar legendas changeAvatar, // Trocar avatar setRegion, // Definir região // Conexão Manual (v2.1.0+) connect, // Conectar a container específico } = useVLibrasPlayer(options); ``` ### Classe VLibrasPlayer ```typescript interface VLibrasPlayerOptions { translatorUrl?: string; targetPath?: string; region?: 'BR' | 'PT'; enableStats?: boolean; onLoad?: () => void; } // Uso da Classe const player = new VLibrasPlayer(options); player.load(containerElement); await player.translate(text); ``` // Métodos de controle translate, // Traduzir texto play, // Reproduzir pause, // Pausar stop, // Parar repeat, // Repetir // Configurações ## 🎨 Exemplos Avançados ### Exemplo com Callbacks e Estados ```typescript 'use client'; import { useRef, useState } from 'react'; import { useVLibrasPlayer } from 'vlibras-player-nextjs'; export default function AdvancedExample() { const containerRef = useRef<HTMLDivElement>(null); const [status, setStatus] = useState('Aguardando...'); const [translatedText, setTranslatedText] = useState(''); const { translate, play, pause, stop, setSpeed, isReady, isLoading, error, player } = useVLibrasPlayer({ autoInit: true, containerRef, region: 'BR', targetPath: '/vlibras/target', onLoad: () => setStatus('Player carregado!'), onTranslateStart: (text) => { setStatus(`Traduzindo: ${text}`); setTranslatedText(text); }, onTranslateEnd: (gloss) => setStatus(`Glosa: ${gloss}`), onError: (error) => setStatus(`Erro: ${error}`) }); const handleTranslate = async () => { const text = prompt('Digite o texto para traduzir:'); if (text && text.trim()) { try { await translate(text); } catch (err) { console.error('Erro na tradução:', err); } } }; return ( <div className="vlibras-demo"> <div ref={containerRef} className="vlibras-container" /> <div className="controls"> <button onClick={handleTranslate} disabled={!isReady}> 📝 Traduzir Texto </button> <button onClick={() => play()} disabled={!isReady}> ▶️ Play </button> <button onClick={pause} disabled={!isReady}> ⏸️ Pause </button> <button onClick={stop} disabled={!isReady}> ⏹️ Stop </button> <button onClick={() => setSpeed(1.5)} disabled={!isReady}> ⚡ Velocidade 1.5x </button> </div> <div className="status"> <p><strong>Status:</strong> {status}</p> <p><strong>Player Status:</strong> {player.status}</p> <p><strong>Carregado:</strong> {player.loaded ? 'Sim' : 'Não'}</p> <p><strong>Pronto:</strong> {isReady ? 'Sim' : 'Não'}</p> <p><strong>Carregando:</strong> {isLoading ? 'Sim' : 'Não'}</p> {translatedText && <p><strong>Último texto:</strong> {translatedText}</p>} {error && <p style={{ color: 'red' }}><strong>Erro:</strong> {error}</p>} </div> </div> ); } ``` ### Conexão Manual Avançada ```typescript 'use client'; import { useRef, useEffect, useState } from 'react'; import { useVLibrasPlayer } from 'vlibras-player-nextjs'; export default function ManualConnectionExample() { const [selectedContainer, setSelectedContainer] = useState<string>('container1'); const container1Ref = useRef<HTMLDivElement>(null); const container2Ref = useRef<HTMLDivElement>(null); const { connect, translate, isReady } = useVLibrasPlayer({ autoInit: true, // Sem containerRef para conexão manual }); const handleContainerChange = (containerId: string) => { setSelectedContainer(containerId); const container = containerId === 'container1' ? container1Ref.current : container2Ref.current; if (container) { connect(container); } }; return ( <div> <div className="container-selection"> <button onClick={() => handleContainerChange('container1')}> Conectar ao Container 1 </button> <button onClick={() => handleContainerChange('container2')}> Conectar ao Container 2 </button> </div> <div className="containers"> <div ref={container1Ref} className={`vlibras-container ${selectedContainer === 'container1' ? 'active' : ''}`} style={{ border: selectedContainer === 'container1' ? '2px solid blue' : '1px solid gray' }} /> <div ref={container2Ref} className={`vlibras-container ${selectedContainer === 'container2' ? 'active' : ''}`} style={{ border: selectedContainer === 'container2' ? '2px solid blue' : '1px solid gray' }} /> </div> <button onClick={() => translate("Olá!")} disabled={!isReady}> Traduzir no Container Ativo </button> </div> ); } ``` ## ⚙️ Configuração ### Next.js (next.config.js) ```javascript /** @type {import('next').NextConfig} */ const nextConfig = { // Configurações para WebGL/Unity webpack: (config) => { config.resolve.fallback = { ...config.resolve.fallback, fs: false, }; return config; }, // Headers para WebGL async headers() { return [ { source: '/vlibras/target/:path*', headers: [ { key: 'Cross-Origin-Embedder-Policy', value: 'require-corp', }, { key: 'Cross-Origin-Opener-Policy', value: 'same-origin', }, ], }, ]; }, }; module.exports = nextConfig; ``` ### Estrutura de Arquivos ``` public/ vlibras/ target/ playerweb.data.unityweb playerweb.json playerweb.wasm.code.unityweb playerweb.wasm.framework.unityweb UnityLoader.js ``` Os arquivos Unity são incluídos automaticamente na biblioteca, mas você pode substituí-los colocando os arquivos na pasta `public/vlibras/target/`. ## 🔄 Migração ### De v2.1.0 para v2.1.1 A v2.1.1 é **100% retrocompatível** e resolve automaticamente o problema de duplicação: #### ✅ Sem Mudanças Necessárias ```typescript // Seu código existente continua funcionando perfeitamente const { translate, isReady } = useVLibrasPlayer({ autoInit: true, containerRef }); // ✅ Agora SEM duplicação de containers automático! ``` #### 🚀 Benefícios Automáticos da v2.1.1: - **Performance melhorada**: Sem containers duplicados - **Menos uso de memória**: Cleanup automático de recursos - **Estabilidade**: Comportamento consistente em re-renders - **React StrictMode**: Funciona perfeitamente com modo estrito ### De v2.0.0 para v2.1.1 Migração recomendada em duas etapas: #### ✅ Código Recomendado (v2.1.1) ```typescript const { translate, isReady } = useVLibrasPlayer({ autoInit: true, containerRef // Conexão automática + sem duplicação }); // ✅ API moderna sem problemas de performance ``` #### ❌ Código Antigo (ainda funciona, mas não recomendado) ```typescript const { player, translate } = useVLibrasPlayer({ autoInit: true }); useEffect(() => { if (containerRef.current && player) { // Conexão manual ainda funciona, mas é desnecessária player.load?.(containerRef.current); } }, [player]); ``` ### Do VLibras Original Se você está migrando do VLibras original, a integração é simples: #### Antes (VLibras Original) ```html <div vw class="enabled"> <div vw-access-button class="active"></div> <div vw-plugin-wrapper> <div class="vw-plugin-top-wrapper"></div> </div> </div> <script src="https://vlibras.gov.br/app/vlibras-plugin.js"></script> <script> new window.VLibras.Widget('https://vlibras.gov.br/app'); </script> ``` #### Depois (vlibras-player-nextjs) ```typescript import { useVLibrasPlayer } from 'vlibras-player-nextjs'; const { translate } = useVLibrasPlayer({ autoInit: true, containerRef }); ``` ### Arquivos Unity (public/vlibras/target/) Coloque os arquivos Unity WebGL no diretório público: ``` public/ └── vlibras/ └── target/ ├── UnityLoader.js ├── playerweb.json ├── playerweb.data.unityweb ├── playerweb.wasm.code.unityweb └── playerweb.wasm.framework.unityweb ``` ## ❓ FAQ ### **Hook vs Classe: Qual usar?** **Hook (Recomendado)**: Use para integração simples em componentes React ```typescript const { translate, isReady } = useVLibrasPlayer({ autoInit: true, containerRef }); ``` **Classe**: Use para controle avançado ou integração com frameworks não-React ```typescript const player = new VLibrasPlayer(options); player.load(container); ``` ### **Como corrigir "Player não inicializado"?** **v2.1.0+**: Use `containerRef` para conexão automática ```typescript const containerRef = useRef<HTMLDivElement>(null); const { translate } = useVLibrasPlayer({ autoInit: true, containerRef }); ``` ### **Arquivos Unity não carregam?** 1. Verifique se os arquivos estão em `public/vlibras/target/` 2. Configure os headers CORS no `next.config.js` 3. Use `targetPath: '/vlibras/target'` nas opções ### **Como personalizar o avatar?** ```typescript const { changeAvatar } = useVLibrasPlayer({ autoInit: true, containerRef }); // Trocar para avatar feminino changeAvatar('anya'); // Trocar para avatar masculino changeAvatar('icaro'); ``` ### **Funciona com SSR/SSG?** Sim! Use `'use client'` no componente que usa o VLibras: ```typescript 'use client'; import { useVLibrasPlayer } from 'vlibras-player-nextjs'; ``` ## 🎯 Compatibilidade -**Next.js 13+** (App Router e Pages Router) -**React 18+** -**TypeScript 5+** -**Node.js 16+** -**Navegadores modernos** (Chrome 80+, Firefox 74+, Safari 13+) -**SSR/SSG** com Next.js -**Webpack 5+** -**Vite 4+** ## 📊 Performance - 📦 **Tamanho do bundle**: ~14MB (inclui arquivos Unity WebGL) -**Carregamento inicial**: ~2-3s (dependendo da conexão) - 🔄 **Tradução**: ~500ms-1s por frase - 💾 **Uso de memória**: ~50-100MB durante reprodução ## 🛠️ Desenvolvimento ```bash # Clonar repositório git clone https://github.com/Luca-Sousa/vlibras-player-web-nextjs.git # Instalar dependências npm install # Desenvolvimento npm run dev # Build npm run build # Testes npm run test # Verificação de tipos npm run type-check ``` ## 📄 Licença Este projeto está licenciado sob a [LGPL v3.0](LICENSE) - veja o arquivo LICENSE para detalhes. O VLibras é uma tecnologia desenvolvida pelo [Governo Federal do Brasil](https://www.vlibras.gov.br/). ## 🤝 Contribuição Contribuições são bem-vindas! Por favor, leia nosso [guia de contribuição](CONTRIBUTING.md) antes de submeter um PR. ### Como contribuir: 1. 🍴 Fork o projeto 2. 🌟 Crie uma branch para sua feature (`git checkout -b feature/AmazingFeature`) 3. 💾 Commit suas mudanças (`git commit -m 'Add some AmazingFeature'`) 4. 📤 Push para a branch (`git push origin feature/AmazingFeature`) 5. 🔀 Abra um Pull Request ## 📞 Suporte - 📋 **Issues**: [GitHub Issues](https://github.com/Luca-Sousa/vlibras-player-web-nextjs/issues) - 📧 **Email**: [contato](mailto:lucas.sousa.ldev@gmail.com) - 📱 **NPM**: [vlibras-player-nextjs](https://www.npmjs.com/package/vlibras-player-nextjs) ## 🙏 Agradecimentos - [VLibras](https://www.vlibras.gov.br/) - Tecnologia original - [Unity Technologies](https://unity.com/) - WebGL Runtime - [Next.js Team](https://nextjs.org/) - Framework - [React Team](https://reactjs.org/) - Biblioteca --- <div align="center"> **vlibras-player-nextjs v2.1.1** - *Acessibilidade em Libras para React e Next.js* 🤟 [![NPM](https://img.shields.io/npm/v/vlibras-player-nextjs)](https://www.npmjs.com/package/vlibras-player-nextjs) [![Downloads](https://img.shields.io/npm/dm/vlibras-player-nextjs)](https://www.npmjs.com/package/vlibras-player-nextjs) [![License](https://img.shields.io/badge/license-LGPLv3-blue.svg)](LICENSE) </div> /> </div> <div className="flex gap-2"> <button onClick={handleTranslate} disabled={isTranslating || !text.trim()} className="bg-blue-500 text-white px-4 py-2 rounded disabled:opacity-50" > {isTranslating ? 'Traduzindo...' : 'Traduzir'} </button> <button onClick={() => playerRef.current?.play()} className="bg-green-500 text-white px-4 py-2 rounded" > Play </button> <button onClick={() => playerRef.current?.pause()} className="bg-yellow-500 text-white px-4 py-2 rounded" > Pause </button> <button onClick={() => playerRef.current?.stop()} className="bg-red-500 text-white px-4 py-2 rounded" > Stop </button> </div> </div> </div> ); } ``` ## 🤝 Contribuindo Contribuições são bem-vindas! Por favor, leia nosso [guia de contribuição](CONTRIBUTING.md) para mais detalhes. ## 📄 Licença Este projeto está licenciado sob a [LGPL-3.0](LICENSE) - veja o arquivo LICENSE para detalhes. ## 👥 Créditos - **Equipe VLibras Original:** Criadores da tecnologia base - **Comunidade Next.js:** Inspiração e melhores práticas - **Contribuidores:** Todos que ajudaram a modernizar esta biblioteca --- <div align="center"> <p>Feito com ❤️ para democratizar o acesso à Libras na web</p> </div>