# PO UI - Biblioteca de Componentes Angular ## Introdução O PO UI é uma biblioteca abrangente de componentes de interface de usuário para Angular, desenvolvida para acelerar o desenvolvimento de aplicações empresariais modernas. Fornece mais de 50 componentes reutilizáveis, incluindo tabelas, formulários, gráficos, navegação e muito mais, todos seguindo padrões de design consistentes e acessibilidade. A biblioteca é distribuída em cinco pacotes principais: `@po-ui/ng-components` (componentes UI core), `@po-ui/ng-templates` (páginas pré-construídas), `@po-ui/ng-storage` (abstração de armazenamento local), `@po-ui/ng-sync` (sincronização offline-first) e `@po-ui/ng-code-editor` (editor de código baseado em Monaco). O PO UI oferece suporte completo para aplicações offline-first através do pacote `@po-ui/ng-sync`, que implementa event sourcing e sincronização automática de dados. Além disso, fornece templates dinâmicos que podem ser configurados via metadados, permitindo criar páginas CRUD completas sem escrever HTML manualmente. A biblioteca é otimizada para Angular 19 e suporta internacionalização (i18n) em português, inglês, espanhol e russo. --- ## APIs e Funções Principais ### Instalação e Configuração Inicial **Instalação do PO UI via Angular CLI** ```bash # Criar novo projeto Angular ng new my-po-project --skip-install # Instalar dependências npm install # Adicionar PO UI ao projeto ng add @po-ui/ng-components # Adicionar templates (opcional) ng add @po-ui/ng-templates # Adicionar storage (opcional) ng add @po-ui/ng-storage # Iniciar aplicação ng serve ``` ```typescript // app.module.ts - Configuração básica import { NgModule } from '@angular/core'; import { BrowserModule } from '@angular/platform-browser'; import { PoModule } from '@po-ui/ng-components'; import { PoTemplatesModule } from '@po-ui/ng-templates'; import { AppComponent } from './app.component'; @NgModule({ declarations: [AppComponent], imports: [ BrowserModule, PoModule, PoTemplatesModule ], bootstrap: [AppComponent] }) export class AppModule { } ``` --- ### PoButton - Componente de Botão **Botão interativo com suporte a ícones, tamanhos e estados** ```typescript import { Component } from '@angular/core'; @Component({ selector: 'app-example', template: ` ` }) export class ExampleComponent { @ViewChild('myButton') button: PoButtonComponent; isLoading = false; handleSave() { this.isLoading = true; console.log('Salvando dados...'); setTimeout(() => this.isLoading = false, 2000); } handleCancel() { console.log('Operação cancelada'); } focusButton() { this.button.focus(); } } ``` --- ### PoTable - Tabela de Dados com Paginação **Tabela avançada com ordenação, filtros, seleção e ações** ```typescript import { Component, OnInit, ViewChild } from '@angular/core'; import { PoTableColumn, PoTableAction, PoTableComponent } from '@po-ui/ng-components'; @Component({ selector: 'app-users-table', template: ` ` }) export class UsersTableComponent implements OnInit { @ViewChild('userTable') table: PoTableComponent; columns: Array = [ { property: 'id', label: 'Código', type: 'number', width: '10%' }, { property: 'name', label: 'Nome', type: 'string', width: '30%' }, { property: 'email', label: 'E-mail', type: 'link', width: '30%' }, { property: 'status', label: 'Status', type: 'label', width: '15%', labels: [ { value: 'active', label: 'Ativo', color: 'success' }, { value: 'inactive', label: 'Inativo', color: 'danger' } ] }, { property: 'birthdate', label: 'Nascimento', type: 'date', width: '15%' } ]; items = [ { id: 1, name: 'Maria Silva', email: 'maria@email.com', status: 'active', birthdate: '1990-05-15' }, { id: 2, name: 'João Santos', email: 'joao@email.com', status: 'inactive', birthdate: '1985-08-22' }, { id: 3, name: 'Ana Costa', email: 'ana@email.com', status: 'active', birthdate: '1992-03-10' } ]; actions: Array = [ { action: this.editUser.bind(this), label: 'Editar', icon: 'po-icon-edit' }, { action: this.deleteUser.bind(this), label: 'Excluir', icon: 'po-icon-delete', type: 'danger' } ]; ngOnInit() { console.log('Tabela inicializada com', this.items.length, 'registros'); } editUser(user: any) { console.log('Editando usuário:', user); } deleteUser(user: any) { this.table.removeItem(user); console.log('Usuário removido:', user); } onSort(sortedColumn: any) { console.log('Ordenado por:', sortedColumn.column.property, sortedColumn.type); } getSelectedUsers() { const selected = this.table.getSelectedRows(); console.log('Usuários selecionados:', selected); return selected; } updateUser(oldUser: any, newUser: any) { this.table.updateItem(oldUser, newUser); } } ``` --- ### PoNotificationService - Notificações Toast **Serviço para exibir notificações temporárias ao usuário** ```typescript import { Component } from '@angular/core'; import { PoNotificationService } from '@po-ui/ng-components'; @Component({ selector: 'app-notifications-demo', template: ` ` }) export class NotificationsDemoComponent { constructor(private poNotification: PoNotificationService) {} showSuccess() { this.poNotification.success('Dados salvos com sucesso!'); } showError() { this.poNotification.error('Erro ao processar a requisição.'); } showWarning() { this.poNotification.warning('Atenção: Esta ação não pode ser desfeita.'); } showInfo() { this.poNotification.information('Processamento em andamento...'); } showWithAction() { this.poNotification.success({ message: 'Arquivo enviado!', duration: 5000, action: () => { console.log('Ação customizada executada'); }, actionLabel: 'Visualizar' }); } } ``` --- ### PoModal - Diálogo Modal **Componente de modal com ações primárias e secundárias** ```typescript import { Component, ViewChild } from '@angular/core'; import { PoModalComponent, PoModalAction } from '@po-ui/ng-components'; @Component({ selector: 'app-modal-demo', template: `

Tem certeza que deseja excluir este registro?

Esta ação não poderá ser desfeita.

` }) export class ModalDemoComponent { @ViewChild('modal', { static: true }) modal: PoModalComponent; confirmAction: PoModalAction = { action: () => { this.deleteRecord(); this.modal.close(); }, label: 'Confirmar', danger: true }; cancelAction: PoModalAction = { action: () => { this.modal.close(); }, label: 'Cancelar' }; deleteRecord() { console.log('Registro excluído'); } openModal() { this.modal.open(); } } ``` --- ### PoPageDynamicTable - Página Dinâmica de Tabela **Página CRUD completa gerada a partir de metadados** ```typescript import { Component } from '@angular/core'; import { PoPageDynamicTableActions, PoPageDynamicTableField } from '@po-ui/ng-templates'; @Component({ selector: 'app-customers', template: ` ` }) export class CustomersComponent { serviceApi = 'https://api.example.com/customers'; actions: PoPageDynamicTableActions = { new: '/customers/new', edit: '/customers/edit/:id', remove: true, detail: '/customers/detail/:id' }; fields: Array = [ { property: 'id', key: true, visible: false }, { property: 'name', label: 'Nome', filter: true, gridColumns: 6 }, { property: 'email', label: 'E-mail', filter: true, gridColumns: 6 }, { property: 'phone', label: 'Telefone', gridColumns: 4 }, { property: 'city', label: 'Cidade', filter: true, gridColumns: 4 }, { property: 'status', label: 'Status', type: 'label', gridColumns: 4, labels: [ { value: 'active', label: 'Ativo', color: 'success' }, { value: 'inactive', label: 'Inativo', color: 'danger' } ] } ]; pageCustomActions = [ { label: 'Exportar', action: this.exportData.bind(this), icon: 'po-icon-export' }, { label: 'Importar', action: this.importData.bind(this), icon: 'po-icon-import' } ]; tableCustomActions = [ { label: 'Enviar E-mail', action: this.sendEmail.bind(this), icon: 'po-icon-mail' } ]; exportData() { console.log('Exportando dados...'); } importData() { console.log('Importando dados...'); } sendEmail(customer: any) { console.log('Enviando e-mail para:', customer.email); } } ``` ```typescript // Configuração via rota // app-routing.module.ts import { Routes } from '@angular/router'; import { PoPageDynamicTableComponent } from '@po-ui/ng-templates'; const routes: Routes = [ { path: 'products', component: PoPageDynamicTableComponent, data: { serviceApi: 'https://api.example.com/products', serviceMetadataApi: 'https://api.example.com/products/metadata' } } ]; // Resposta esperada do endpoint de metadados (GET) /* { "version": 1, "title": "Produtos", "fields": [ { "property": "id", "key": true, "disabled": true }, { "property": "name", "label": "Nome do Produto", "filter": true }, { "property": "price", "label": "Preço", "type": "currency" }, { "property": "stock", "label": "Estoque", "type": "number" } ], "keepFilters": true, "actions": { "new": "/products/new", "edit": "/products/edit/:id", "remove": true } } */ ``` --- ### PoStorageService - Armazenamento Local **Abstração de armazenamento com suporte a múltiplos drivers** ```typescript import { NgModule } from '@angular/core'; import { PoStorageModule, PoStorageConfig } from '@po-ui/ng-storage'; const storageConfig: PoStorageConfig = { name: 'myapp_db', storeName: 'myapp_store', driverOrder: ['lokijs', 'websql', 'indexeddb', 'localstorage'] }; @NgModule({ imports: [ PoStorageModule.forRoot(storageConfig) ] }) export class AppModule { } ``` ```typescript import { Component, OnInit } from '@angular/core'; import { PoStorageService } from '@po-ui/ng-storage'; @Component({ selector: 'app-storage-demo', template: `
Exemplo de Storage - Veja o console
` }) export class StorageDemoComponent implements OnInit { constructor(private poStorage: PoStorageService) {} async ngOnInit() { // Salvar dados await this.poStorage.set('user', { name: 'João', age: 30, preferences: { theme: 'dark' } }); console.log('Dados salvos'); // Buscar dados const user = await this.poStorage.get('user'); console.log('Usuário:', user); // Trabalhar com arrays const tasks = [ { id: 1, title: 'Tarefa 1', done: false }, { id: 2, title: 'Tarefa 2', done: true } ]; await this.poStorage.set('tasks', tasks); // Adicionar item ao array await this.poStorage.appendItemToArray('tasks', { id: 3, title: 'Tarefa 3', done: false } ); // Buscar item específico const task = await this.poStorage.getItemByField('tasks', 'id', 2); console.log('Tarefa encontrada:', task); // Remover item do array await this.poStorage.removeItemFromArray('tasks', 'id', 2); // Iterar sobre todas as chaves await this.poStorage.forEach((value, key, index) => { console.log(`${index}: ${key} =`, value); }); // Listar todas as chaves const keys = await this.poStorage.keys(); console.log('Chaves armazenadas:', keys); // Verificar existência const exists = await this.poStorage.exists('user'); console.log('Usuário existe:', exists); // Remover item específico await this.poStorage.remove('tasks'); // Limpar tudo (usar com cautela!) // await this.poStorage.clear(); } } ``` --- ### PoSyncService - Sincronização Offline **Sincronização automática de dados para aplicações offline-first** ```typescript import { NgModule } from '@angular/core'; import { PoSyncModule } from '@po-ui/ng-sync'; @NgModule({ imports: [PoSyncModule] }) export class AppModule { } ``` ```typescript import { Component, OnInit } from '@angular/core'; import { PoSyncService, PoSyncSchema } from '@po-ui/ng-sync'; @Component({ selector: 'app-sync-demo' }) export class SyncDemoComponent implements OnInit { constructor(private poSync: PoSyncService) {} async ngOnInit() { // Definir schemas const schemas: Array = [ { name: 'customers', api: 'https://api.example.com/customers', idField: 'id', fields: ['id', 'name', 'email', 'phone'], pageSize: 20 }, { name: 'orders', api: 'https://api.example.com/orders', idField: 'orderId', fields: ['orderId', 'customerId', 'total', 'date'], pageSize: 50 } ]; // Preparar sincronização await this.poSync.prepare(schemas, { period: 30, // Sincronizar a cada 30 segundos type: 'wifi' // Sincronizar apenas em WiFi }); // Carregar dados iniciais this.poSync.loadData().subscribe( data => console.log('Dados carregados:', data), error => console.error('Erro ao carregar:', error) ); // Obter modelo para manipular dados const customersModel = this.poSync.getModel('customers'); // Criar novo cliente (será sincronizado automaticamente) await customersModel.create({ name: 'Maria Santos', email: 'maria@example.com', phone: '11999999999' }); // Buscar todos os clientes const allCustomers = await customersModel.find().exec(); console.log('Clientes:', allCustomers); // Buscar com filtro const filtered = await customersModel.find() .where('name').eq('Maria Santos') .exec(); console.log('Cliente encontrado:', filtered); // Atualizar cliente await customersModel.update( { id: 1 }, { email: 'novo@example.com' } ); // Remover cliente await customersModel.remove({ id: 1 }); // Inserir requisição HTTP customizada na fila await this.poSync.insertHttpCommand({ url: 'https://api.example.com/custom-action', method: 'POST', body: { action: 'process', data: [1, 2, 3] } }); // Monitorar respostas de sincronização this.poSync.getResponses().subscribe( response => { console.log('Resposta da sincronização:', response); if (response.error) { console.error('Erro:', response.error); } } ); // Notificações pós-sincronização this.poSync.onSync().subscribe( () => console.log('Sincronização concluída!') ); // Desabilitar sincronização temporariamente this.poSync.disableSync(); // Reabilitar sincronização this.poSync.enableSync(); // Sincronização manual // this.poSync.sync(); } async ngOnDestroy() { // Limpar dados de sincronização (usar com cautela) // await this.poSync.destroy(); } } ``` --- ### PoCodeEditor - Editor de Código Monaco **Editor de código avançado com syntax highlighting e sugestões** ```typescript import { NgModule } from '@angular/core'; import { PoCodeEditorModule } from '@po-ui/ng-code-editor'; // Registrar linguagem customizada (opcional) const customLanguage = { language: 'terraform', options: { keywords: ['resource', 'variable', 'output', 'provider', 'module'], operators: ['=', '==', '!=', '>', '<'], symbols: /[=>

Modo Diff (Comparação)

` }) export class EditorDemoComponent { code = `function hello() { console.log('Hello, World!'); } hello();`; language = 'javascript'; originalCode = 'const x = 10;'; modifiedCode = 'const x = 20;'; suggestions = [ { label: 'logInfo', kind: 'Function', documentation: 'Registra informação no console', insertText: 'console.info(${1:message});' }, { label: 'asyncFunction', kind: 'Snippet', documentation: 'Função assíncrona', insertText: 'async function ${1:name}() {\n ${2:// código}\n}' } ]; onCodeChange(newCode: string) { console.log('Código alterado:', newCode); // Validar, formatar ou salvar o código } } ``` --- ### Formulários Dinâmicos com Campos **Campos de entrada com validação e máscaras** ```typescript import { Component } from '@angular/core'; import { FormBuilder, FormGroup, Validators } from '@angular/forms'; @Component({ selector: 'app-dynamic-form', template: `
` }) export class DynamicFormComponent { form: FormGroup; maritalStatusOptions = [ { label: 'Solteiro(a)', value: 'single' }, { label: 'Casado(a)', value: 'married' }, { label: 'Divorciado(a)', value: 'divorced' }, { label: 'Viúvo(a)', value: 'widowed' } ]; citiesOptions = [ { label: 'São Paulo', value: 'sp' }, { label: 'Rio de Janeiro', value: 'rj' }, { label: 'Belo Horizonte', value: 'bh' }, { label: 'Curitiba', value: 'cwb' }, { label: 'Porto Alegre', value: 'poa' } ]; constructor(private fb: FormBuilder) { this.form = this.fb.group({ name: ['', [Validators.required, Validators.minLength(3)]], email: ['', [Validators.required, Validators.email]], cpf: ['', Validators.required], birthdate: [''], salary: [''], maritalStatus: [''], city: [''], notes: [''], notifications: [true] }); } onSubmit() { if (this.form.valid) { console.log('Formulário enviado:', this.form.value); // Processar dados } } clearForm() { this.form.reset({ notifications: true }); } } ``` --- ## Resumo e Padrões de Integração O PO UI oferece uma solução completa para desenvolvimento de aplicações Angular empresariais, com foco em produtividade e consistência. Os principais casos de uso incluem: (1) criação rápida de interfaces CRUD usando componentes `PoPageDynamicTable`, `PoPageDynamicEdit` e `PoPageDynamicDetail`, onde toda a configuração é feita via metadados vindos do backend; (2) desenvolvimento de aplicações offline-first usando `PoSyncService` para sincronização automática de dados, ideal para aplicações móveis e ambientes com conectividade instável; (3) construção de dashboards e relatórios com componentes `PoTable`, `PoChart`, `PoWidget` e `PoGauge`; (4) implementação de fluxos de trabalho complexos com validação de formulários usando a extensa coleção de campos de entrada (`PoInput`, `PoCombo`, `PoLookup`, etc.). Os padrões de integração recomendados incluem: utilizar o sistema de injeção de dependências do Angular para acessar serviços como `PoNotificationService`, `PoDialogService` e `PoStorageService`; configurar módulos via `forRoot()` no módulo raiz da aplicação (ex: `PoStorageModule.forRoot(config)`); usar programação reativa com RxJS para operações assíncronas, especialmente com `PoSyncService` e `PoPageDynamicService`; aproveitar o suporte nativo a formulários reativos do Angular (`FormGroup`, `FormControl`) em conjunto com os componentes de entrada do PO UI; implementar internacionalização através do `PoI18nService` para suportar múltiplos idiomas; e seguir as diretrizes de acessibilidade fornecidas, ajustando o tamanho dos componentes via `p-components-size` e configurando o tema através do `PoThemeService` para garantir conformidade com padrões AA de acessibilidade.