A maioria das interfaces de sistemas internos existe apesar da arquitetura, não por causa dela. O Nimbus.js inverte essa equação: cada componente tem uma responsabilidade precisa, comunica-se por eventos e compõe-se por declaração — em um único arquivo JavaScript, sem dependências externas, sem etapa de build.
Frameworks genéricos são construídos para cobrir todos os casos possíveis — o que os torna complexos demais para quem quer resolver um problema específico com precisão. O Nimbus.js tomou o caminho oposto. E cada decisão tem um motivo claro.
Frameworks universais carregam a complexidade de todos os casos que nunca existirão no seu sistema. O Nimbus.js foi projetado para um contexto definido — cada componente resolve um problema concreto, cada detalhe serve a uma decisão deliberada, não a uma possibilidade hipotética.
Não há npm install. Não há webpack.config.js. Não há node_modules com dezenas de milhares de arquivos para servir três componentes. Uma tag <script>. A API WM disponível. Interface funcionando.
Cada .add() é uma decisão visível. O que está declarado é exatamente o que existe — sem configuração implícita, sem efeito colateral, sem surpresa para quem mantiver o código daqui a seis meses. A composição de uma janela é a sua própria documentação.
No Nimbus.js, responsabilidade única não é apenas princípio de código — é princípio de design. O Grid exibe dados e emite eventos. A Toolbar oferece ações e filtragem. O Form coleta, valida e notifica. A Window gerencia posição, foco e ciclo de vida.
Nenhum componente sabe o que o outro faz internamente. Eles não se acoplam — comunicam-se exclusivamente por eventos. Você, como desenvolvedor, é o compositor: decide o que acontece quando um evento é disparado, conectando peças independentes em um fluxo coeso.
O resultado é uma arquitetura onde cada parte pode ser substituída, testada e compreendida de forma isolada — sem que o sistema inteiro precise ser decifrado para fazer uma mudança pontual.
.on() é uma decisão de fluxo — visível, substituível, testável de forma isolada.A API foi desenhada para ser autoexplicativa. Você lê o código de composição e sabe exatamente o que a janela contém — sem abrir nenhum outro arquivo, sem consultar documentação.
Abra a janela com WM.openWindow(). Adicione componentes com .add(). O encadeamento declara a interface na mesma ordem em que o usuário a verá — simples, eficiente, sem ambiguidade.
WM.openWindow({ title: 'Inventário', width: 720, height: 460 }) .add(toolbar) .add(grid)
Quatro componentes em produção hoje, cada um com responsabilidade única e API coesa. Dezesseis no roadmap — priorizados pela necessidade real do sistema, não por completude teórica.
Disponíveis agora
rowClick, sort. Não sabe o que acontece depois de emitir. Não precisa.submit com os dados — você decide o que fazer com eles.onSearch sem saber que o Grid existe — apenas chama a função recebida.Alta prioridade — em desenvolvimento
alert() nativo com uma experiência consistente.Roadmap — médio prazo
setData() sem recriar o componente.Longo prazo
Três padrões de uso — do mais simples ao mais composto. Em cada um, o código declara a interface e os eventos orquestram o fluxo.
O Grid recebe colunas e dados e entrega ordenação e filtro nativos. A propriedade badge: true coloriza os valores da coluna de status automaticamente por categoria.
O evento rowClick entrega o objeto completo da linha clicada — o Grid não sabe o que acontece depois. Você decide. Essa separação é intencional e é o que torna cada peça substituível.
grid.filter(query) refiltra os dados em tempo real sem recriar a tabela. Conecte-o ao onSearch da Toolbar e a busca instantânea está pronta — zero lógica adicional.
const grid = WM.Grid({ columns: [ { field: 'patrimonio', title: 'Patrimônio', sortable: true, width: '110px' }, { field: 'descricao', title: 'Descrição', sortable: true }, { field: 'status', title: 'Status', badge: true, width: '110px' }, { field: 'responsavel',title: 'Responsável', width: '100px' }, ], data: ativos }) // O Grid emite — você decide o que acontece grid.on('rowClick', row => { abrirEdicao(row) }) WM.openWindow({ title: 'Inventário de Ativos', width: 720, height: 460 }) .add(grid)
A Toolbar não sabe que o Grid existe. Ela recebe uma função — onSearch — e a chama quando o usuário digita. Quem filtra é o Grid. Quem conecta é o desenvolvedor.
Esse é o modelo de coesão do Nimbus.js: componentes independentes orquestrados por código explícito. Nenhuma mágica, nenhum canal oculto, nenhuma dependência implícita.
WM.closeAll() fecha todas as janelas abertas. Útil para reinicializar o estado da interface entre operações críticas sem recarregar a página.
const grid = WM.Grid({ columns: [ { field: 'patrimonio', title: 'Patrimônio', sortable: true }, { field: 'descricao', title: 'Descrição', sortable: true }, { field: 'status', title: 'Status', badge: true }, ], data: ativos }) // Toolbar não conhece o Grid — recebe e chama const toolbar = WM.Toolbar() .addButton({ label: 'Novo', onClick: () => abrirCadastro() }) .addButton({ label: 'Exportar', onClick: () => exportar() }) .addSeparator() .addSearch({ placeholder: 'Buscar...', onSearch: q => grid.filter(q) }) // Você, o compositor, declara a ordem WM.openWindow({ title: 'Inventário', width: 660, height: 440 }) .add(toolbar) .add(grid)
O padrão de edição inline revela o encadeamento de eventos em sua forma mais completa: um clique no Grid inicia a cadeia, o Form coleta e valida, o submit encerra o ciclo.
Cada componente cumpre sua responsabilidade e passa o controle para frente. Nenhum passo está oculto — tudo é código explícito, em sequência, legível de cima para baixo.
'Editar — ' + row.descricao. Contexto imediato para o usuário, custo zero para o desenvolvedor.
// Grid dispara → Form recebe → Window encerra grid.on('rowClick', row => { const form = WM.Form() .addField({ name: 'patrimonio', label: 'Nº Patrimônio', value: row.patrimonio }) .addField({ name: 'descricao', label: 'Descrição', value: row.descricao }) .addField({ name: 'status', label: 'Status', type: 'select', options: ['Em uso', 'Disponível', 'Manutenção'], value: row.status }) .addField({ name: 'responsavel', label: 'Responsável', value: row.responsavel }) // Form coleta, valida e emite — você fecha form.on('submit', data => { salvar(data); winEd.close() }) const winEd = WM.openWindow({ title: 'Editar — ' + row.descricao, width: 480, height: 380 }).add(form) })
Sem gerenciador de pacotes. Sem etapa de build. Sem configuração de ambiente. A inclusão do script é suficiente — a API WM está disponível imediatamente.
Execute npm install @coreops/nimbus ou baixe nimbus.js e adicione via <script>. Compatível com qualquer template HTML sem modificação de ambiente ou processo de build.
A API global WM estará pronta: openWindow, Grid, Form e Toolbar — sem instanciação prévia, sem cerimônia.
Adicione componentes com .add() e conecte-os por eventos com .on(). O código declara a interface e orquestra o fluxo — explícito, legível, sem surpresas.