@thibezer/ui-components-kit 2.0.0 → 2.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +78 -0
- package/README.md +760 -739
- package/dist/botao.cjs +1 -1
- package/dist/botao.js +1 -1
- package/dist/camadas.cjs +175 -142
- package/dist/camadas.js +1335 -1054
- package/dist/canvas.cjs +99 -140
- package/dist/canvas.js +5552 -1283
- package/dist/components/ui-barra-ferramentas/tipos.d.ts +2 -2
- package/dist/components/ui-barra-ferramentas/ui-paleta-ferramentas.d.ts +2 -2
- package/dist/components/ui-camadas/camadas-adapters.d.ts +45 -0
- package/dist/components/ui-camadas/camadas-arvore-renderer.d.ts +9 -0
- package/dist/components/ui-camadas/camadas-drag-drop.d.ts +4 -0
- package/dist/components/ui-camadas/camadas-metricas.d.ts +8 -1
- package/dist/components/ui-camadas/camadas-persistencia.d.ts +5 -0
- package/dist/components/ui-camadas/camadas-rodape.d.ts +5 -0
- package/dist/components/ui-camadas/index.d.ts +1 -0
- package/dist/components/ui-camadas/tipos.d.ts +8 -0
- package/dist/components/ui-camadas/ui-camadas.d.ts +11 -0
- package/dist/components/ui-canvas-cad/cad-estilos-externos.d.ts +16 -0
- package/dist/components/ui-canvas-cad/cad-eventos-canvas.d.ts +4 -0
- package/dist/components/ui-canvas-cad/cad-feicoes.d.ts +262 -0
- package/dist/components/ui-canvas-cad/cad-ferramentas-barra.d.ts +15 -0
- package/dist/components/ui-canvas-cad/cad-snap.d.ts +32 -0
- package/dist/components/ui-canvas-cad/cad-toolbar-painel.d.ts +1 -0
- package/dist/components/ui-canvas-cad/ui-canvas-cad.d.ts +143 -0
- package/dist/components/ui-lista-flutuante/lista-flutuante-posicionamento.d.ts +2 -0
- package/dist/components/ui-lista-flutuante/ui-lista-flutuante.d.ts +1 -0
- package/dist/components/ui-seletor-mapa-base/ui-seletor-mapa-base.d.ts +3 -0
- package/dist/components/ui-tabela/tabela-atributos-sync.d.ts +3 -0
- package/dist/components/ui-tabela/tabela-localizador.d.ts +8 -1
- package/dist/components/ui-tabela/tabela-orquestrador-dados.d.ts +4 -0
- package/dist/components/ui-tabela/tabela-selecao.d.ts +19 -9
- package/dist/components/ui-tabela/tipos.d.ts +6 -0
- package/dist/components/ui-tabela/ui-tabela.d.ts +41 -2
- package/dist/components/ui-tabela-propriedades/avaliador-expressao.d.ts +0 -5
- package/dist/components/ui-tabela-propriedades/propriedades-dom-utils.d.ts +17 -1
- package/dist/components/ui-tabela-propriedades/propriedades-flutuante.d.ts +2 -0
- package/dist/components/ui-tabela-propriedades/propriedades-gerenciador-valores.d.ts +10 -1
- package/dist/components/ui-tabela-propriedades/propriedades-render-arvore.d.ts +3 -1
- package/dist/components/ui-tabela-propriedades/ui-tabela-propriedades.d.ts +5 -1
- package/dist/core/alvo-digitavel.d.ts +1 -0
- package/dist/core/index.d.ts +1 -0
- package/dist/core/svg-seguro.d.ts +10 -0
- package/dist/core.cjs +1 -1
- package/dist/core.js +12 -10
- package/dist/custom-elements.json +16586 -12150
- package/dist/data.cjs +1 -1
- package/dist/data.js +51 -46
- package/dist/forms.cjs +1 -1
- package/dist/forms.js +1 -1
- package/dist/gerencigeo-canvas/canvas_interacao.d.ts +18 -0
- package/dist/gerencigeo-canvas/curva_leaflet.d.ts +21 -0
- package/dist/gerencigeo-canvas/feature_adapters.d.ts +35 -0
- package/dist/gerencigeo-canvas/feature_algoritmos.d.ts +45 -0
- package/dist/gerencigeo-canvas/feature_amostra.d.ts +4 -0
- package/dist/gerencigeo-canvas/feature_caixa.d.ts +19 -0
- package/dist/gerencigeo-canvas/feature_cluster.d.ts +61 -0
- package/dist/gerencigeo-canvas/feature_cursores.d.ts +17 -0
- package/dist/gerencigeo-canvas/feature_curvas.d.ts +43 -0
- package/dist/gerencigeo-canvas/feature_desenho.d.ts +55 -0
- package/dist/gerencigeo-canvas/feature_desenho_controle.d.ts +91 -0
- package/dist/gerencigeo-canvas/feature_edicao_ops.d.ts +46 -0
- package/dist/gerencigeo-canvas/feature_editor_vertices.d.ts +80 -0
- package/dist/gerencigeo-canvas/feature_formas.d.ts +7 -0
- package/dist/gerencigeo-canvas/feature_hud.d.ts +23 -0
- package/dist/gerencigeo-canvas/feature_indice.d.ts +36 -0
- package/dist/gerencigeo-canvas/feature_metricas.d.ts +16 -0
- package/dist/gerencigeo-canvas/feature_popup.d.ts +31 -0
- package/dist/gerencigeo-canvas/feature_selecao.d.ts +38 -0
- package/dist/gerencigeo-canvas/feature_simplificacao.d.ts +15 -0
- package/dist/gerencigeo-canvas/feature_snap.d.ts +25 -0
- package/dist/gerencigeo-canvas/feature_types.d.ts +101 -0
- package/dist/gerencigeo-canvas/feature_versoes.d.ts +19 -0
- package/dist/gerencigeo-canvas/index.d.ts +21 -0
- package/dist/gerencigeo-canvas/layer_hit_test.d.ts +30 -0
- package/dist/gerencigeo-canvas/layer_manager.d.ts +11 -3
- package/dist/gerencigeo-canvas/layer_pane_ops.d.ts +9 -0
- package/dist/gerencigeo-canvas/mapa_controller.d.ts +1 -0
- package/dist/gerencigeo-canvas/mapa_pontos_shapes.d.ts +24 -5
- package/dist/gerencigeo-canvas/renderers/feicoes_renderer.d.ts +89 -0
- package/dist/gerencigeo-canvas/renderers/vector_points_renderer.d.ts +1 -0
- package/dist/gerencigeo-canvas/renderers/vector_polygons_renderer.d.ts +2 -2
- package/dist/gerencigeo-canvas/types.d.ts +12 -0
- package/dist/gerencigeo-canvas/utils.d.ts +4 -2
- package/dist/index.cjs +1 -1
- package/dist/index.js +132 -121
- package/dist/leaflet-DcO7uRC-.cjs +1 -0
- package/dist/{leaflet-DkaFZYc5.js → leaflet-PPDKB6Dd.js} +37 -37
- package/dist/mapa.cjs +1 -1
- package/dist/mapa.js +1 -1
- package/dist/register.cjs +1 -1
- package/dist/register.js +4 -4
- package/dist/seletor-mapa-base.cjs +13 -13
- package/dist/seletor-mapa-base.js +101 -51
- package/dist/svg-seguro-BsbNQqpd.js +50 -0
- package/dist/svg-seguro-C76iLlAZ.cjs +1 -0
- package/dist/tabela.cjs +1 -1
- package/dist/tabela.js +41 -36
- package/dist/tipos-elementos.d.ts +26 -7
- package/dist/tipos-vue.d.ts +24 -7
- package/dist/tools.cjs +1 -1
- package/dist/tools.js +1 -1
- package/dist/ui-botao-BOOnP8ds.cjs +12 -0
- package/dist/ui-botao-DfqSivHl.js +165 -0
- package/dist/{ui-paleta-ferramentas-BIytXQLh.js → ui-paleta-ferramentas-CEZYcN4J.js} +18 -27
- package/dist/{ui-paleta-ferramentas-DqLY51qa.cjs → ui-paleta-ferramentas-Dbj1kBS9.cjs} +6 -6
- package/dist/{ui-switch-DWLgVVnT.js → ui-switch-BcOqOkiV.js} +124 -96
- package/dist/ui-switch-D7iPKDj-.cjs +53 -0
- package/dist/ui-tabela-propriedades-BBr5sqki.cjs +145 -0
- package/dist/{ui-tabela-propriedades-BNcE6VLX.js → ui-tabela-propriedades-Boy7I5yW.js} +1304 -1072
- package/package.json +169 -169
- package/dist/leaflet-Cw6tqYFh.cjs +0 -1
- package/dist/ui-switch-yZIn3IW0.cjs +0 -53
- package/dist/ui-tabela-propriedades-D3pyQvyy.cjs +0 -145
package/README.md
CHANGED
|
@@ -1,739 +1,760 @@
|
|
|
1
|
-
# 🎨 UI Components Kit - Web Components Nativos & Universais
|
|
2
|
-
|
|
3
|
-
Biblioteca de **Web Components Nativos Universais e Agnósticos**, construída no padrão oficial **W3C Custom Elements + Shadow DOM**, com TypeScript, Design Tokens em CSS modular e Vite.
|
|
4
|
-
|
|
5
|
-
Projetada para funcionar em **qualquer linguagem, framework ou sistema web** (HTML puro, React, Next.js, Vue, Angular, Svelte, PHP, Django, WordPress, Blazor, etc.) com **zero dependências externas** (exceto `<ui-mapa>` e `<ui-canvas-cad>`, que usam o Leaflet como dependência opcional).
|
|
6
|
-
|
|
7
|
-
---
|
|
8
|
-
|
|
9
|
-
## 📑 Índice
|
|
10
|
-
|
|
11
|
-
1. [Por que Web Components?](#-por-que-web-components)
|
|
12
|
-
2. [Como Importar na sua Aplicação](#-como-importar-na-sua-aplicação)
|
|
13
|
-
- [Opção 1: CDN / Script Tag (HTML puro, PHP, Django)](#opção-1-cdn--script-tag-html-puro-php-django)
|
|
14
|
-
- [Opção 2: NPM / Módulos ES (React, Vue, Next.js, Vite)](#opção-2-npm--módulos-es-react-vue-nextjs-vite)
|
|
15
|
-
3. [Como Controlar os Componentes (5 Pilares)](#-como-controlar-os-componentes-5-pilares)
|
|
16
|
-
4. [⚡ Recursos Inteligentes de Alta Produtividade](#-recursos-inteligentes-de-alta-produtividade)
|
|
17
|
-
- [Ações Declarativas "Zero-JS" (Triggers Nativos)](#1-ações-declarativas-zero-js-triggers-nativos)
|
|
18
|
-
- [Formulários Automáticos com FormData Nativo (W3C FACE)](#2-formulários-automáticos-com-formdata-nativo-w3c-face)
|
|
19
|
-
- [Barramento Global de Orquestração (UIBus)](#3-barramento-global-de-orquestração-uibus)
|
|
20
|
-
- [Tabelas Autônomas com Auto-Fetch Remoto](#4-tabelas-autônomas-com-auto-fetch-remoto)
|
|
21
|
-
5. [💻 Exemplos de Uso por Tecnologia](#-exemplos-de-uso-por-tecnologia)
|
|
22
|
-
- [HTML Puro + JavaScript](#html-puro--javascript)
|
|
23
|
-
- [React / Next.js](#react--nextjs)
|
|
24
|
-
- [Vue.js](#vuejs)
|
|
25
|
-
- [Iframes / Microfrontends](#iframes--microfrontends)
|
|
26
|
-
6. [🧩 Catálogo de Componentes & Referência](#-catálogo-de-componentes--referência)
|
|
27
|
-
7. [🛠️ Como Executar e Compilar Localmente](#️-como-executar-e-compilar-localmente)
|
|
28
|
-
|
|
29
|
-
---
|
|
30
|
-
|
|
31
|
-
## 🎯 Por que Web Components?
|
|
32
|
-
|
|
33
|
-
* 🌐 **100% Universal e Agnóstico**: Funciona em qualquer stack sem necessidade de bibliotecas intermediárias.
|
|
34
|
-
* 🛡️ **Encapsulamento Total (Shadow DOM)**: O CSS da sua aplicação nunca quebra o componente, e o CSS do componente nunca vaza para o seu site.
|
|
35
|
-
* 📐 **Design Tokens Centralizados**: Variáveis CSS personalizáveis para cores, tipografia, raios e densidade.
|
|
36
|
-
* 🚀 **Suporte a Altíssima Densidade**: Otimizado para interfaces densas e técnicas (GIS, CAD, Topografia de 15px a 20px de altura) até interfaces fluidas modernas.
|
|
37
|
-
|
|
38
|
-
---
|
|
39
|
-
|
|
40
|
-
## 📦 Como Importar na sua Aplicação
|
|
41
|
-
|
|
42
|
-
### Opção 1: CDN / Script Tag (HTML puro, PHP, Django)
|
|
43
|
-
|
|
44
|
-
Adicione as tags no `<head>` ou antes do fechamento do `</body>`:
|
|
45
|
-
|
|
46
|
-
```html
|
|
47
|
-
<!-- 1. Design Tokens e Estilos Globais -->
|
|
48
|
-
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@thibezer/ui-components-kit@1/dist/ui-kit.css">
|
|
49
|
-
|
|
50
|
-
<!-- 2. Biblioteca dos Componentes (Módulo ES) -->
|
|
51
|
-
<script type="module" src="https://cdn.jsdelivr.net/npm/@thibezer/ui-components-kit@1/dist/index.js"></script>
|
|
52
|
-
|
|
53
|
-
<!-- 3. Uso imediato no HTML -->
|
|
54
|
-
<ui-botao-primario variante="primary">Clique Aqui</ui-botao-primario>
|
|
55
|
-
```
|
|
56
|
-
|
|
57
|
-
> **Mapa e CAD via CDN (`<ui-mapa>`, `<ui-canvas-cad>`)**: esses componentes dependem do [Leaflet](https://leafletjs.com/), importado como `leaflet` (especificador "bare"), que o navegador só resolve com um *import map*. Declare-o **antes** do script da biblioteca:
|
|
58
|
-
>
|
|
59
|
-
> ```html
|
|
60
|
-
> <script type="importmap">
|
|
61
|
-
> { "imports": { "leaflet": "https://cdn.jsdelivr.net/npm/leaflet@1.9.4/+esm" } }
|
|
62
|
-
> </script>
|
|
63
|
-
> ```
|
|
64
|
-
>
|
|
65
|
-
> Os demais componentes não precisam do Leaflet. Com npm, basta `npm install leaflet`.
|
|
66
|
-
|
|
67
|
-
### Opção 2: NPM / Módulos ES (React, Vue, Next.js, Vite)
|
|
68
|
-
|
|
69
|
-
Instale pelo npm:
|
|
70
|
-
|
|
71
|
-
```bash
|
|
72
|
-
npm install @thibezer/ui-components-kit
|
|
73
|
-
```
|
|
74
|
-
|
|
75
|
-
> O pacote é publicado já compilado (`dist/`) e **não executa build na instalação**, então funciona em CI/CD e em servidores com `npm ci --omit=dev`. A antiga instalação por URL Git (`git+https://github.com/...`) não é mais suportada: o repositório não versiona `dist/`.
|
|
76
|
-
|
|
77
|
-
No ponto de entrada da sua aplicação (`main.ts`, `index.js` ou `App.tsx`):
|
|
78
|
-
|
|
79
|
-
```typescript
|
|
80
|
-
// 1. Estilos globais obrigatórios (tokens CSS)
|
|
81
|
-
import '@thibezer/ui-components-kit/style.css';
|
|
82
|
-
|
|
83
|
-
// 2. Biblioteca completa (ou escolha os submódulos abaixo)
|
|
84
|
-
import '@thibezer/ui-components-kit';
|
|
85
|
-
```
|
|
86
|
-
|
|
87
|
-
#### 🚀 Importação Modular e Otimizada (Sub-paths)
|
|
88
|
-
|
|
89
|
-
Pague apenas pelo que utilizar. Importe por domínio de funcionalidade ou por componente específico:
|
|
90
|
-
|
|
91
|
-
O export map expõe explicitamente os pontos de entrada canônicos (ESM em `.js`, CommonJS em `.cjs` e tipos `.d.ts`):
|
|
92
|
-
|
|
93
|
-
| Subpath | Arquivo (ESM) |
|
|
94
|
-
|---|---|
|
|
95
|
-
| `@thibezer/ui-components-kit` | `dist/index.js` |
|
|
96
|
-
| `@thibezer/ui-components-kit/camadas` | `dist/camadas.js` |
|
|
97
|
-
| `@thibezer/ui-components-kit/forms` | `dist/forms.js` |
|
|
98
|
-
| `@thibezer/ui-components-kit/feedback` | `dist/feedback.js` |
|
|
99
|
-
| `@thibezer/ui-components-kit/tabela` | `dist/tabela.js` |
|
|
100
|
-
| `@thibezer/ui-components-kit/style.css` | `dist/ui-kit.css` (100% autocontido, sem `@import`) |
|
|
101
|
-
|
|
102
|
-
##### 1. Por Domínio / Categoria:
|
|
103
|
-
```typescript
|
|
104
|
-
import '@thibezer/ui-components-kit/forms'; // Campos, Select, Checkbox, Radio, Switch (~8 kB gzip)
|
|
105
|
-
import '@thibezer/ui-components-kit/feedback'; // Modais, Drawers, Alertas, Toasts, Tooltips, Skeletons (~6 kB gzip)
|
|
106
|
-
import '@thibezer/ui-components-kit/data'; // Tabela, Tabela-Propriedades, Stat KPI, Badge (~4 kB gzip)
|
|
107
|
-
import '@thibezer/ui-components-kit/tools'; // Ribbon CAD/Office e Paleta de Ferramentas (~10 kB gzip)
|
|
108
|
-
import '@thibezer/ui-components-kit/core'; // Apenas UIBus, Zero-JS e ListenerBag (< 1 kB gzip)
|
|
109
|
-
import '@thibezer/ui-components-kit/canvas'; // Mesa CAD vetorial e motor GIS (~33 kB gzip)
|
|
110
|
-
import '@thibezer/ui-components-kit/camadas'; // Painel de Camadas GIS/CAD redimensionável (~21 kB gzip)
|
|
111
|
-
import '@thibezer/ui-components-kit/mapa'; // Mapa Geográfico Leaflet (~3 kB gzip)
|
|
112
|
-
```
|
|
113
|
-
|
|
114
|
-
##### 2. Granular por Componente (Ultra Leve):
|
|
115
|
-
```typescript
|
|
116
|
-
import '@thibezer/ui-components-kit/botao'; // Apenas <ui-botao> e <ui-botao-primario> (~3.4 kB gzip)
|
|
117
|
-
import '@thibezer/ui-components-kit/campo-texto'; // Apenas <ui-campo-texto> com FACE e anti-zoom (~3.9 kB gzip)
|
|
118
|
-
import '@thibezer/ui-components-kit/modal'; // Apenas <ui-modal> com bottom-sheet mobile (~3.3 kB gzip)
|
|
119
|
-
import '@thibezer/ui-components-kit/card'; // Apenas <ui-card> com elevação (~2.3 kB gzip)
|
|
120
|
-
import '@thibezer/ui-components-kit/tabela'; // Apenas <ui-tabela> virtualizada
|
|
121
|
-
```
|
|
122
|
-
|
|
123
|
-
> **Zero Overhead**: Uma tela que utilize apenas `<ui-botao>` e `<ui-campo-texto>` importa menos de **8 kB gzip**, sem carregar nada de Leaflet, CAD, GIS ou virtualização.
|
|
124
|
-
|
|
125
|
-
---
|
|
126
|
-
|
|
127
|
-
## 🎛️ Como Controlar os Componentes (5 Pilares)
|
|
128
|
-
|
|
129
|
-
```text
|
|
130
|
-
┌─────────────────────────────────────────────────────────────┐
|
|
131
|
-
│ SISTEMA EXTERNO │
|
|
132
|
-
└──────┬───────────────▲─────────────────┬─────────────────▲──┘
|
|
133
|
-
│ │ │ │
|
|
134
|
-
1. Atributos 4. Eventos Custom 2. Propriedades 3. Métodos
|
|
135
|
-
(HTML) (ui-*) (Objetos/Listas) (Imperativo)
|
|
136
|
-
│ │ │ │
|
|
137
|
-
┌──────▼───────────────┴─────────────────▼─────────────────┴──┐
|
|
138
|
-
│ WEB COMPONENT (<ui-*>) │
|
|
139
|
-
└─────────────────────────────────────────────────────────────┘
|
|
140
|
-
```
|
|
141
|
-
|
|
142
|
-
### 1. Atributos HTML (Controle Declarativo)
|
|
143
|
-
Configurações simples passadas diretamente nas tags:
|
|
144
|
-
```html
|
|
145
|
-
<ui-campo-texto label="CPF" placeholder="000.000.000-00" obrigatorio></ui-campo-texto>
|
|
146
|
-
<ui-modal id="meu-modal" titulo="Confirmar Exclusão"></ui-modal>
|
|
147
|
-
```
|
|
148
|
-
|
|
149
|
-
---
|
|
150
|
-
|
|
151
|
-
### 📏 Ajuste de Altura e Dimensionamento Inteligente (Zero Atrito)
|
|
152
|
-
|
|
153
|
-
Os campos de texto (`<ui-campo-texto>`), listas flutuantes/selects (`<ui-lista-flutuante>`, `<ui-select>`) e botões (`<ui-botao-primario>`) possuem 4 formas flexíveis de ajuste de altura:
|
|
154
|
-
|
|
155
|
-
#### 1. Via Atributo de Tamanho Predefinido (`tamanho` ou `densidade`):
|
|
156
|
-
```html
|
|
157
|
-
<!-- Compacto (26px) - Ideal para Toolbars CAD/GIS, tabelas e alta densidade -->
|
|
158
|
-
<ui-campo-texto tamanho="sm" placeholder="26px Compacto"></ui-campo-texto>
|
|
159
|
-
<ui-lista-flutuante tamanho="sm" placeholder="Selecione..."></ui-lista-flutuante>
|
|
160
|
-
|
|
161
|
-
<!-- Padrão (34px) - Padrão moderno e equilibrado para formulários e modais -->
|
|
162
|
-
<ui-campo-texto tamanho="md" placeholder="34px Padrão"></ui-campo-texto>
|
|
163
|
-
<ui-lista-flutuante tamanho="md" placeholder="Selecione..."></ui-lista-flutuante>
|
|
164
|
-
|
|
165
|
-
<!-- Conforto / Touch (42px) - Otimizado para dispositivos móveis e telas sensíveis ao toque -->
|
|
166
|
-
<ui-campo-texto tamanho="lg" placeholder="42px Conforto"></ui-campo-texto>
|
|
167
|
-
<ui-lista-flutuante tamanho="lg" placeholder="Selecione..."></ui-lista-flutuante>
|
|
168
|
-
```
|
|
169
|
-
|
|
170
|
-
#### 2. Via Atributo de Altura Explícita (`altura` ou `height`):
|
|
171
|
-
```html
|
|
172
|
-
<!-- Define a altura exata em pixels diretamente no elemento -->
|
|
173
|
-
<ui-campo-texto altura="38" placeholder="Altura de 38px"></ui-campo-texto>
|
|
174
|
-
<ui-lista-flutuante altura="44px" placeholder="Altura de 44px"></ui-lista-flutuante>
|
|
175
|
-
<ui-botao-primario altura="40">Salvar</ui-botao-primario>
|
|
176
|
-
```
|
|
177
|
-
|
|
178
|
-
#### 3. Via Variável CSS Customizável (`--ui-campo-altura`):
|
|
179
|
-
```css
|
|
180
|
-
/* No seu CSS global ou no container pai */
|
|
181
|
-
.meu-formulario {
|
|
182
|
-
--ui-campo-altura: 36px; /* Aplica instantaneamente em todos os inputs, selects e botões filhos */
|
|
183
|
-
}
|
|
184
|
-
```
|
|
185
|
-
|
|
186
|
-
#### 4. Via Barramento Global de Densidade (`UIBus`):
|
|
187
|
-
```javascript
|
|
188
|
-
import { UIBus } from '@thibezer/ui-components-kit';
|
|
189
|
-
|
|
190
|
-
// Altera a densidade de toda a aplicação em tempo real:
|
|
191
|
-
UIBus.definirDensidade('compacta'); // 26px
|
|
192
|
-
UIBus.definirDensidade('padrao'); // 34px
|
|
193
|
-
UIBus.definirDensidade('relaxada'); // 42px
|
|
194
|
-
UIBus.definirDensidade(38); // Valor numérico em px customizado
|
|
195
|
-
```
|
|
196
|
-
|
|
197
|
-
---
|
|
198
|
-
|
|
199
|
-
### 2. Propriedades JavaScript (Dados Complexos)
|
|
200
|
-
Para enviar arrays e objetos complexos:
|
|
201
|
-
```javascript
|
|
202
|
-
const tabela = document.querySelector('ui-tabela');
|
|
203
|
-
tabela.colunas = [
|
|
204
|
-
{ id: 'ponto', rotulo: 'Ponto', ordenavel: true },
|
|
205
|
-
{ id: 'altitude', rotulo: 'Altitude (m)' }
|
|
206
|
-
];
|
|
207
|
-
tabela.dados = [
|
|
208
|
-
{ ponto: 'P-01', altitude: '542,15' },
|
|
209
|
-
{ ponto: 'P-02', altitude: '545,30' }
|
|
210
|
-
];
|
|
211
|
-
```
|
|
212
|
-
|
|
213
|
-
### 3. Métodos Imperativos (Ações Diretas)
|
|
214
|
-
Comandos diretos chamados na instância do elemento:
|
|
215
|
-
```javascript
|
|
216
|
-
const modal = document.getElementById('meu-modal');
|
|
217
|
-
modal.abrir();
|
|
218
|
-
modal.fechar();
|
|
219
|
-
```
|
|
220
|
-
|
|
221
|
-
### 4. Eventos Customizados Nativos (`ui-*`)
|
|
222
|
-
Escuta de eventos disparados pelas interações do usuário:
|
|
223
|
-
```javascript
|
|
224
|
-
const campo = document.querySelector('ui-campo-texto');
|
|
225
|
-
campo.addEventListener('ui-input', (e) => {
|
|
226
|
-
console.log('Texto digitado:', e.detail.value);
|
|
227
|
-
});
|
|
228
|
-
```
|
|
229
|
-
|
|
230
|
-
> **Mutação de usuário vs. programática (`<ui-camadas>`)**: eventos saem do componente **somente** em resposta a interações físicas (clique, drag-and-drop, teclado). Atribuir `painel.layers = [...]`, alterar atributos (`camada-ativa`, `colapsado`, `mapa-base-ativo`...) ou chamar métodos públicos (`definirCamadaAtiva`, `selecionarFeicao`, `limparSelecao`, `colapsar`, `definirAltura`...) apenas atualiza o DOM interno — sem redisparar eventos. Isso elimina loops de sincronização em apps reativos (React, Vue, Svelte). Para forçar a emissão numa chamada programática, passe `emitirEvento = true` (ex.: `painel.definirCamadaAtiva('lotes', true)`).
|
|
231
|
-
|
|
232
|
-
### 5. Serviços Globais e Helpers
|
|
233
|
-
Utilitários prontos para uso sem necessidade de instanciar elementos:
|
|
234
|
-
```javascript
|
|
235
|
-
import { UIToast, UIBus } from '@thibezer/ui-components-kit';
|
|
236
|
-
|
|
237
|
-
UIToast.notificar({
|
|
238
|
-
tipo: 'sucesso',
|
|
239
|
-
titulo: 'Registro Salvo!',
|
|
240
|
-
mensagem: 'Os dados foram sincronizados.',
|
|
241
|
-
duracao: 4000
|
|
242
|
-
});
|
|
243
|
-
```
|
|
244
|
-
|
|
245
|
-
### 6. Escala de Elevação (z-index)
|
|
246
|
-
Todos os componentes flutuantes consomem tokens de elevação previsíveis (com fallback), definidos em `ui-kit.css`. Sobrescreva-os no `:root` da aplicação para encaixar a pilha do kit entre os HUDs e modais do seu app:
|
|
247
|
-
```css
|
|
248
|
-
:root {
|
|
249
|
-
--ui-z-workspace-hud: 500; /* <ui-camadas flutuante>, <ui-seletor-mapa-base>, toolbars do canvas */
|
|
250
|
-
--ui-z-docked-bar: 600; /* <ui-ribbon> recolhido, <ui-tabela-propriedades flutuante> */
|
|
251
|
-
--ui-z-drawer: 700; /* <ui-drawer> e backdrop */
|
|
252
|
-
--ui-z-modal: 1000; /* <ui-modal> e backdrop */
|
|
253
|
-
--ui-z-popover: 1050; /* menus suspensos/contexto, <ui-select> (acima do modal, funciona dentro dele) */
|
|
254
|
-
--ui-z-toast: 1100; /* UIToast */
|
|
255
|
-
--ui-z-tooltip: 1200; /* <ui-tooltip> */
|
|
256
|
-
}
|
|
257
|
-
```
|
|
258
|
-
|
|
259
|
-
### 7. Acessibilidade Nativa de Rótulos
|
|
260
|
-
`<ui-input>` (alias de `<ui-campo-texto>`), `<ui-select>` e `<ui-switch>` geram IDs únicos internamente e associam o rótulo visível ao controle nativo do Shadow DOM — o projeto consumidor não precisa gerenciar IDs:
|
|
261
|
-
```html
|
|
262
|
-
<ui-input label="Nome"></ui-input> <!-- <label for> ↔ <input> interno -->
|
|
263
|
-
<ui-select label="Cidade">...</ui-select> <!-- aria-labelledby = rótulo + valor atual -->
|
|
264
|
-
<ui-switch label="Modo escuro"></ui-switch> <!-- role="switch" aria-labelledby -->
|
|
265
|
-
|
|
266
|
-
<!-- Sem o atributo label, o nome acessível vem de fora do Shadow DOM: -->
|
|
267
|
-
<label>Telefone <ui-input></ui-input></label>
|
|
268
|
-
<ui-switch aria-label="Camada visível"></ui-switch>
|
|
269
|
-
```
|
|
270
|
-
|
|
271
|
-
### 8. Temas Claro e Escuro
|
|
272
|
-
Sem configuração, o kit **segue o tema do sistema operacional** (`prefers-color-scheme`). Para fixar um tema, use o atributo na raiz — ou em qualquer elemento, para fixar só aquele trecho:
|
|
273
|
-
```html
|
|
274
|
-
<html data-tema="escuro"> <!-- ou "claro"; também aceitos: class="dark|light" e data-theme="dark|light" -->
|
|
275
|
-
<aside data-tema="claro">…</aside> <!-- trecho claro dentro de uma página escura -->
|
|
276
|
-
```
|
|
277
|
-
```javascript
|
|
278
|
-
UIBus.definirTema('auto'); // volta a seguir o SO
|
|
279
|
-
UIBus.on('tema:alterado', ({ tema }) => { /* também dispara quando o SO muda, se o tema não estiver fixado */ });
|
|
280
|
-
```
|
|
281
|
-
Os componentes recebem o tema **apenas pelos tokens de cor** (`--ui-cor-*`, `--ui-sombra-*`), que atravessam o Shadow DOM. Todo token de texto atinge contraste **WCAG AA (4,5:1)** nos dois temas, inclusive sobre fundos tingidos de status e no texto sobre a cor primária e o botão destrutivo — verificado em `tests/tema.test.ts`.
|
|
282
|
-
|
|
283
|
-
| Token | Uso |
|
|
284
|
-
| :--- | :--- |
|
|
285
|
-
| `--ui-cor-texto-sucesso` / `-erro` / `-alerta` / `-info` | Texto e tons de status (alertas, badges, toasts) |
|
|
286
|
-
| `--ui-cor-texto-sobre-status` | Texto sobre fundo sólido de status (badge sólido) |
|
|
287
|
-
| `--ui-cor-fundo-recuado` | Faixas rebaixadas (rodapés de modal e drawer) |
|
|
288
|
-
| `--ui-sombra-sm` / `-md` / `-lg` | Sombras: densas no escuro, suaves no claro |
|
|
289
|
-
|
|
290
|
-
### 9. Tipografia e Raios
|
|
291
|
-
Todos os componentes usam apenas dois tokens de família de fonte e uma escala de raios derivada de `--ui-raio-borda`. Sobrescreva no `:root` (a escala é calculada lá):
|
|
292
|
-
```css
|
|
293
|
-
:root {
|
|
294
|
-
--ui-fonte-base: 'Roboto', sans-serif; /* textos da interface */
|
|
295
|
-
--ui-fonte-codigo: 'JetBrains Mono', monospace; /* coordenadas, valores técnicos, código */
|
|
296
|
-
|
|
297
|
-
--ui-raio-borda: 4px; /* base: botões, campos, menus */
|
|
298
|
-
/* derivados automaticamente: --ui-raio-sm (2/3), --ui-raio-lg (5/3), --ui-raio-xl (8/3) */
|
|
299
|
-
/* --ui-raio-borda: 0 → interface totalmente reta */
|
|
300
|
-
}
|
|
301
|
-
```
|
|
302
|
-
|
|
303
|
-
### 10. Estilização Interna com `::part`
|
|
304
|
-
O Shadow DOM isola o CSS, mas os elementos internos principais são expostos com `part`, com nomes consistentes entre componentes (uma regra serve para vários):
|
|
305
|
-
|
|
306
|
-
| Componente | Parts |
|
|
307
|
-
| :--- | :--- |
|
|
308
|
-
| `<ui-botao>` / `<ui-botao-primario>` | `base`, `spinner` |
|
|
309
|
-
| `<ui-campo-texto>` / `<ui-input>` | `rotulo`, `campo`, `input`, `icone`, `icone-esquerda`, `icone-direita`, `ajuda` |
|
|
310
|
-
| `<ui-lista-flutuante>` / `<ui-select>` | `rotulo`, `campo`, `valor`, `seta`, `lista`, `opcao`, `opcao-selecionada` |
|
|
311
|
-
| `<ui-checkbox>`, `<ui-radio>`, `<ui-switch>` | `base`, `controle`, `indicador`, `rotulo` |
|
|
312
|
-
| `<ui-segmented>` | `base`, `indicador`, `opcao`, `opcao-selecionada` |
|
|
313
|
-
| `<ui-modal>`, `<ui-drawer>` | `fundo`, `painel`, `cabecalho`, `titulo`, `descricao` (drawer), `fechar`, `corpo`, `rodape` |
|
|
314
|
-
| `<ui-card>` | `base`, `midia`, `cabecalho`, `corpo`, `rodape` |
|
|
315
|
-
| `<ui-badge>` / `<ui-chip>` | `base`, `rotulo`, `remover` |
|
|
316
|
-
| `<ui-alerta>` / toasts | `base`, `icone`, `conteudo`, `titulo`, `mensagem`, `acao`, `fechar`, `progresso` |
|
|
317
|
-
| `<ui-tooltip>` | `balao`, `texto`, `seta` |
|
|
318
|
-
| `<ui-tabela>` | `base`, `tabela`, `celula-cabecalho`, `ordenar`, `linha`, `linha-selecionada`, `celula`, `vazio`, `carregando` |
|
|
319
|
-
|
|
320
|
-
```css
|
|
321
|
-
ui-campo-texto::part(campo) { border-width: 2px; }
|
|
322
|
-
ui-modal::part(painel) { max-width: 720px; }
|
|
323
|
-
ui-tabela::part(linha-selecionada) { background: #0b3d2a; }
|
|
324
|
-
:is(ui-checkbox, ui-radio, ui-switch)::part(rotulo) { font-weight: 600; }
|
|
325
|
-
```
|
|
326
|
-
|
|
327
|
-
---
|
|
328
|
-
|
|
329
|
-
## ⚡ Recursos Inteligentes de Alta Produtividade
|
|
330
|
-
|
|
331
|
-
### 1. Ações Declarativas "Zero-JS" (Triggers Nativos)
|
|
332
|
-
Você pode acionar modais, fechar janelas, disparar notificações toast ou copiar textos **sem escrever nenhuma linha de JavaScript**, apenas adicionando atributos nas tags HTML:
|
|
333
|
-
|
|
334
|
-
```html
|
|
335
|
-
<!-- Abrir Modal sem JS -->
|
|
336
|
-
<ui-botao-primario target-modal="modal-exclusao" variante="destrutivo">
|
|
337
|
-
Excluir Registro
|
|
338
|
-
</ui-botao-primario>
|
|
339
|
-
|
|
340
|
-
<!-- Modal com Fechamento e Toast automáticos -->
|
|
341
|
-
<ui-modal id="modal-exclusao" titulo="Confirmação">
|
|
342
|
-
Tem certeza que deseja excluir?
|
|
343
|
-
<div slot="rodape">
|
|
344
|
-
<ui-botao-primario dismiss-modal variante="secundario">Cancelar</ui-botao-primario>
|
|
345
|
-
<ui-botao-primario dismiss-modal toast-sucesso="Excluído com sucesso!" variante="destrutivo">
|
|
346
|
-
Confirmar
|
|
347
|
-
</ui-botao-primario>
|
|
348
|
-
</div>
|
|
349
|
-
</ui-modal>
|
|
350
|
-
|
|
351
|
-
<!-- Copiar Texto em 1 Clique -->
|
|
352
|
-
<ui-campo-texto id="input-token" value="SIGEF-2026-X88"></ui-campo-texto>
|
|
353
|
-
<ui-botao-primario copiar-texto="#input-token" copiar-mensagem="Token copiado!">
|
|
354
|
-
Copiar Chave
|
|
355
|
-
</ui-botao-primario>
|
|
356
|
-
```
|
|
357
|
-
|
|
358
|
-
#### Tabela de Atributos Zero-JS Disponíveis:
|
|
359
|
-
| Atributo | Descrição | Exemplo de Uso |
|
|
360
|
-
| :--- | :--- | :--- |
|
|
361
|
-
| `target-modal="id"` | Abre o modal com o ID especificado ao clicar. | `target-modal="modal-login"` |
|
|
362
|
-
| `dismiss-modal` | Fecha o modal atual (ou o especificado por ID). | `dismiss-modal` |
|
|
363
|
-
| `toast-sucesso="msg"` | Dispara uma notificação flutuante de sucesso. | `toast-sucesso="Salvo com sucesso!"` |
|
|
364
|
-
| `toast-erro="msg"` | Dispara uma notificação flutuante de erro. | `toast-erro="Falha na conexão."` |
|
|
365
|
-
| `toast-alerta="msg"` | Dispara uma notificação flutuante de aviso. | `toast-alerta="Preencha os campos obrigatórios."` |
|
|
366
|
-
| `copiar-texto="texto\|#id"` | Copia o texto ou o valor do elemento referenciado. | `copiar-texto="#campo-pix"` |
|
|
367
|
-
| `limpar-form="id"` | Reseta todos os campos do formulário indicado. | `limpar-form="form-cadastro"` |
|
|
368
|
-
| `alternar-tema` | Alterna entre tema claro e escuro globalmente (a partir do tema em vigor, inclusive o do SO). | `alternar-tema` |
|
|
369
|
-
|
|
370
|
-
---
|
|
371
|
-
|
|
372
|
-
### 2. Formulários Automáticos com `FormData` Nativo (W3C FACE)
|
|
373
|
-
Todos os campos (`<ui-campo-texto>`, `<ui-lista-flutuante>`, `<ui-checkbox>`, `<ui-radio>`, `<ui-switch>`) implementam a especificação oficial de **Form-Associated Custom Elements**.
|
|
374
|
-
|
|
375
|
-
Isso significa que você extrai os dados de todos os campos de uma única vez, sem ler um por um:
|
|
376
|
-
|
|
377
|
-
```html
|
|
378
|
-
<form id="form-imovel">
|
|
379
|
-
<ui-campo-texto name="denominacao" label="Nome da Fazenda" value="Boa Vista"></ui-campo-texto>
|
|
380
|
-
<ui-campo-texto name="municipio" label="Município" value="Uberlândia"></ui-campo-texto>
|
|
381
|
-
<ui-checkbox name="georreferenciado" label="Georreferenciado" marcado value="sim"></ui-checkbox>
|
|
382
|
-
|
|
383
|
-
<ui-botao-primario type="submit">Salvar Imóvel</ui-botao-primario>
|
|
384
|
-
</form>
|
|
385
|
-
```
|
|
386
|
-
|
|
387
|
-
```javascript
|
|
388
|
-
const form = document.getElementById('form-imovel');
|
|
389
|
-
|
|
390
|
-
form.addEventListener('submit', (e) => {
|
|
391
|
-
e.preventDefault();
|
|
392
|
-
|
|
393
|
-
// Extrai TODOS os campos em 1 única linha nativa:
|
|
394
|
-
const dados = Object.fromEntries(new FormData(form));
|
|
395
|
-
console.log(dados);
|
|
396
|
-
// Resultado: { denominacao: "Boa Vista", municipio: "Uberlândia", georreferenciado: "sim" }
|
|
397
|
-
});
|
|
398
|
-
```
|
|
399
|
-
|
|
400
|
-
Assim como nos campos nativos, **Enter** em um `<ui-campo-texto>` submete o formulário pelo botão de envio padrão (`<ui-botao-primario type="submit">` ou `<button>`), que também pode estar fora do `<form>` com `form="id-do-form"`. Para impedir, chame `preventDefault()` no `keydown`. O `name`/`value` do botão que submeteu chega como `e.submitter` (use `new FormData(form, e.submitter)`), e gatilhos Zero-JS em botões `disabled` ou `carregando` são ignorados.
|
|
401
|
-
|
|
402
|
-
---
|
|
403
|
-
|
|
404
|
-
### 3. Barramento Global de Orquestração (`UIBus`)
|
|
405
|
-
O `UIBus` é uma central reativa que permite comandar qualquer componente do sistema ou ouvir eventos sem precisar de `querySelector`:
|
|
406
|
-
|
|
407
|
-
```javascript
|
|
408
|
-
import { UIBus } from '@thibezer/ui-components-kit';
|
|
409
|
-
|
|
410
|
-
// 1. Executar Ações Diretas:
|
|
411
|
-
UIBus.abrirModal('modal-confirmacao');
|
|
412
|
-
UIBus.fecharModal('modal-confirmacao');
|
|
413
|
-
UIBus.notificar({ tipo: 'sucesso', mensagem: 'Operação concluída!' });
|
|
414
|
-
UIBus.copiar('Texto para a área de transferência', 'Copiado!');
|
|
415
|
-
UIBus.definirDensidade('compacta'); // 'compacta' | 'normal' | 'relaxada'
|
|
416
|
-
UIBus.definirTema('escuro'); // 'claro' | 'escuro' | 'auto' (segue o SO); sem argumento, alterna
|
|
417
|
-
UIBus.obterTema(); // tema em vigor: 'claro' | 'escuro'
|
|
418
|
-
|
|
419
|
-
// 2. Comunicação Desacoplada (Pub/Sub):
|
|
420
|
-
UIBus.on('vertice:selecionado', (dadosVertice) => {
|
|
421
|
-
console.log('Vértice selecionado em qualquer tela:', dadosVertice);
|
|
422
|
-
});
|
|
423
|
-
|
|
424
|
-
UIBus.emit('vertice:selecionado', { id: 101, nome: 'M-01', altitude: 432.10 });
|
|
425
|
-
```
|
|
426
|
-
|
|
427
|
-
---
|
|
428
|
-
|
|
429
|
-
### 4. Tabelas Autônomas com Auto-Fetch Remoto
|
|
430
|
-
A `<ui-tabela>` pode buscar dados de uma API remota de forma totalmente autônoma, exibindo indicador de loading, tratando erros e permitindo filtragem instantânea:
|
|
431
|
-
|
|
432
|
-
```html
|
|
433
|
-
<ui-tabela
|
|
434
|
-
id="tabela-vertices"
|
|
435
|
-
src="/api/v1/geodesia/vertices"
|
|
436
|
-
max-height="400px"
|
|
437
|
-
densidade="compacta">
|
|
438
|
-
</ui-tabela>
|
|
439
|
-
```
|
|
440
|
-
|
|
441
|
-
```javascript
|
|
442
|
-
const tabela = document.getElementById('tabela-vertices');
|
|
443
|
-
|
|
444
|
-
// Definir colunas da tabela:
|
|
445
|
-
tabela.colunas = [
|
|
446
|
-
{ id: 'nome_vertice', rotulo: 'Vértice', ordenavel: true },
|
|
447
|
-
{ id: 'este', rotulo: 'Este (m)', ordenavel: true, alinhamento: 'direita' },
|
|
448
|
-
{ id: 'norte', rotulo: 'Norte (m)', ordenavel: true, alinhamento: 'direita' }
|
|
449
|
-
];
|
|
450
|
-
|
|
451
|
-
// Métodos inteligentes disponíveis na tabela:
|
|
452
|
-
tabela.filtrar('M-01'); // Filtra instantaneamente em todas as colunas
|
|
453
|
-
tabela.recarregar(); // Recarrega os dados da API remota
|
|
454
|
-
```
|
|
455
|
-
|
|
456
|
-
---
|
|
457
|
-
|
|
458
|
-
## 💻 Exemplos de Uso por Tecnologia
|
|
459
|
-
|
|
460
|
-
### HTML Puro + JavaScript
|
|
461
|
-
```html
|
|
462
|
-
<!DOCTYPE html>
|
|
463
|
-
<html lang="pt-BR">
|
|
464
|
-
<head>
|
|
465
|
-
<link rel="stylesheet" href="dist/ui-kit.css">
|
|
466
|
-
<script type="module" src="dist/index.js"></script>
|
|
467
|
-
</head>
|
|
468
|
-
<body>
|
|
469
|
-
<ui-campo-texto id="meu-campo" label="Nome do Projeto"></ui-campo-texto>
|
|
470
|
-
<ui-botao-primario target-modal="meu-modal">Abrir Detalhes</ui-botao-primario>
|
|
471
|
-
|
|
472
|
-
<ui-modal id="meu-modal" titulo="Detalhes">
|
|
473
|
-
<p>Conteúdo do modal...</p>
|
|
474
|
-
<div slot="rodape">
|
|
475
|
-
<ui-botao-primario dismiss-modal>Fechar</ui-botao-primario>
|
|
476
|
-
</div>
|
|
477
|
-
</ui-modal>
|
|
478
|
-
|
|
479
|
-
<script>
|
|
480
|
-
document.getElementById('meu-campo').addEventListener('ui-input', (e) => {
|
|
481
|
-
console.log('Digitado:', e.detail.value);
|
|
482
|
-
});
|
|
483
|
-
</script>
|
|
484
|
-
</body>
|
|
485
|
-
</html>
|
|
486
|
-
```
|
|
487
|
-
|
|
488
|
-
---
|
|
489
|
-
|
|
490
|
-
### React / Next.js (SSR & Client Components)
|
|
491
|
-
|
|
492
|
-
A biblioteca é **100% SSR-safe**: todas as classes herdam de `SafeHTMLElement` e o registro de tags utiliza verificações de segurança para ambientes sem DOM (Node.js). Isso garante que você pode importar tipos, classes e constantes tanto no servidor quanto no cliente sem encontrar `ReferenceError: HTMLElement is not defined` ou `customElements is not defined`.
|
|
493
|
-
|
|
494
|
-
#### Tipos no TSX (autocompletar e checagem)
|
|
495
|
-
O pacote gera tipos para todas as tags a partir do Custom Elements Manifest. Registre-os uma vez no `tsconfig.json`:
|
|
496
|
-
|
|
497
|
-
```json
|
|
498
|
-
{ "compilerOptions": { "types": ["@thibezer/ui-components-kit/tipos-react"] } }
|
|
499
|
-
```
|
|
500
|
-
|
|
501
|
-
A partir daí o editor sugere atributos, propriedades e eventos de cada tag, e o TypeScript recusa valores inválidos:
|
|
502
|
-
|
|
503
|
-
```tsx
|
|
504
|
-
<ui-tabela
|
|
505
|
-
colunas={[{ id: 'ponto', rotulo: 'Ponto', ordenavel: true }]} // tipado como TabelaColuna[]
|
|
506
|
-
densidade="compacta" // 'compacta' | 'normal' | 'relaxada'
|
|
507
|
-
onui-sort={(e) => console.log(e.detail)} // eventos ui-* no formato do React 19
|
|
508
|
-
/>
|
|
509
|
-
<ui-tabela densidade="enorme" /> // ❌ erro de tipo
|
|
510
|
-
```
|
|
511
|
-
|
|
512
|
-
Outros JSX (Preact, Solid etc.) podem usar o mapa agnóstico `ElementosUI` de `@thibezer/ui-components-kit/tipos-elementos`.
|
|
513
|
-
|
|
514
|
-
#### No Next.js (App Router):
|
|
515
|
-
|
|
516
|
-
Crie um componente cliente provedor ou registre no topo do seu layout/página cliente:
|
|
517
|
-
|
|
518
|
-
```tsx
|
|
519
|
-
// components/UIProvider.tsx
|
|
520
|
-
'use client';
|
|
521
|
-
|
|
522
|
-
import { useEffect } from 'react';
|
|
523
|
-
import '@thibezer/ui-components-kit/style.css';
|
|
524
|
-
import '@thibezer/ui-components-kit/register'; // Registra todos os Custom Elements com segurança no cliente
|
|
525
|
-
|
|
526
|
-
export function UIProvider({ children }: { children: React.ReactNode }) {
|
|
527
|
-
return <>{children}</>;
|
|
528
|
-
}
|
|
529
|
-
```
|
|
530
|
-
|
|
531
|
-
Ou registre de forma modular apenas o que a tela precisa:
|
|
532
|
-
|
|
533
|
-
```tsx
|
|
534
|
-
// app/dashboard/page.tsx
|
|
535
|
-
'use client';
|
|
536
|
-
|
|
537
|
-
import React, { useEffect, useRef, useState } from 'react';
|
|
538
|
-
import '@thibezer/ui-components-kit/style.css';
|
|
539
|
-
import '@thibezer/ui-components-kit/forms';
|
|
540
|
-
import '@thibezer/ui-components-kit/botao';
|
|
541
|
-
import '@thibezer/ui-components-kit/tabela';
|
|
542
|
-
import { UIBus } from '@thibezer/ui-components-kit/core';
|
|
543
|
-
import type { UITabela } from '@thibezer/ui-components-kit/tabela';
|
|
544
|
-
|
|
545
|
-
export default function DashboardPropriedades() {
|
|
546
|
-
const tabelaRef = useRef<UITabela>(null);
|
|
547
|
-
const [nome, setNome] = useState('');
|
|
548
|
-
|
|
549
|
-
useEffect(() => {
|
|
550
|
-
if (tabelaRef.current) {
|
|
551
|
-
tabelaRef.current.colunas = [
|
|
552
|
-
{ id: 'id', rotulo: 'Código' },
|
|
553
|
-
{ id: 'nome', rotulo: 'Propriedade' }
|
|
554
|
-
];
|
|
555
|
-
tabelaRef.current.dados = [
|
|
556
|
-
{ id: 1, nome: 'Fazenda Santa Luzia' }
|
|
557
|
-
];
|
|
558
|
-
}
|
|
559
|
-
}, []);
|
|
560
|
-
|
|
561
|
-
return (
|
|
562
|
-
<div style={{ padding: 24 }}>
|
|
563
|
-
<ui-campo-texto
|
|
564
|
-
label="Pesquisar Imóvel"
|
|
565
|
-
value={nome}
|
|
566
|
-
onInput={(e: any) => {
|
|
567
|
-
// Os eventos nativos `input`/`change` não têm `detail`: leia o valor do próprio elemento
|
|
568
|
-
const valor = e.target.value;
|
|
569
|
-
setNome(valor);
|
|
570
|
-
tabelaRef.current?.filtrar(valor);
|
|
571
|
-
}}
|
|
572
|
-
></ui-campo-texto>
|
|
573
|
-
|
|
574
|
-
<ui-tabela ref={tabelaRef} max-height="300px" densidade="compacta"></ui-tabela>
|
|
575
|
-
|
|
576
|
-
<ui-botao-primario
|
|
577
|
-
variante="primary"
|
|
578
|
-
onClick={() => UIBus.notificar({ tipo: 'sucesso', mensagem: 'Dados sincronizados!' })}>
|
|
579
|
-
Sincronizar
|
|
580
|
-
</ui-botao-primario>
|
|
581
|
-
</div>
|
|
582
|
-
);
|
|
583
|
-
}
|
|
584
|
-
```
|
|
585
|
-
|
|
586
|
-
---
|
|
587
|
-
|
|
588
|
-
### Vue.js
|
|
589
|
-
|
|
590
|
-
Para autocompletar e checar props e eventos nos templates (Volar), registre os tipos no `tsconfig.json` e informe ao Vue que tags `ui-*` são custom elements:
|
|
591
|
-
|
|
592
|
-
```json
|
|
593
|
-
{ "compilerOptions": { "types": ["@thibezer/ui-components-kit/tipos-vue"] } }
|
|
594
|
-
```
|
|
595
|
-
|
|
596
|
-
```javascript
|
|
597
|
-
// vite.config.js
|
|
598
|
-
vue({ template: { compilerOptions: { isCustomElement: (tag) => tag.startsWith('ui-') } } })
|
|
599
|
-
```
|
|
600
|
-
|
|
601
|
-
```vue
|
|
602
|
-
<template>
|
|
603
|
-
<div class="container">
|
|
604
|
-
<ui-campo-texto
|
|
605
|
-
:value="termoBusca"
|
|
606
|
-
label="Buscar Vértice"
|
|
607
|
-
@ui-input="aoDigitar"
|
|
608
|
-
/>
|
|
609
|
-
|
|
610
|
-
<ui-lista-flutuante
|
|
611
|
-
.itens="opcoes"
|
|
612
|
-
@ui-selecionar="aoSelecionar"
|
|
613
|
-
/>
|
|
614
|
-
|
|
615
|
-
<ui-botao-primario target-modal="modal-confirmacao">
|
|
616
|
-
Confirmar Operação
|
|
617
|
-
</ui-botao-primario>
|
|
618
|
-
</div>
|
|
619
|
-
</template>
|
|
620
|
-
|
|
621
|
-
<script setup>
|
|
622
|
-
import { ref } from 'vue';
|
|
623
|
-
import '@thibezer/ui-components-kit/style.css';
|
|
624
|
-
import '@thibezer/ui-components-kit';
|
|
625
|
-
|
|
626
|
-
const termoBusca = ref('');
|
|
627
|
-
const opcoes = ref([
|
|
628
|
-
{ id: '1', label: 'Marco Geodésico M' },
|
|
629
|
-
{ id: '2', label: 'Ponto Topográfico P' }
|
|
630
|
-
]);
|
|
631
|
-
|
|
632
|
-
function aoDigitar(e) {
|
|
633
|
-
termoBusca.value = e.detail.value;
|
|
634
|
-
}
|
|
635
|
-
|
|
636
|
-
function aoSelecionar(e) {
|
|
637
|
-
console.log('Opção selecionada:', e.detail);
|
|
638
|
-
}
|
|
639
|
-
</script>
|
|
640
|
-
```
|
|
641
|
-
|
|
642
|
-
---
|
|
643
|
-
|
|
644
|
-
### Iframes / Microfrontends
|
|
645
|
-
Comunicação segura entre iframes e sistemas pais via eventos do `UIBus`:
|
|
646
|
-
|
|
647
|
-
```javascript
|
|
648
|
-
// Dentro do Iframe (Filho):
|
|
649
|
-
import { UIBus } from '@thibezer/ui-components-kit';
|
|
650
|
-
|
|
651
|
-
UIBus.on('vertice:salvo', (dados) => {
|
|
652
|
-
window.parent.postMessage({ tipo: 'VERTICE_SALVO', payload: dados }, '*');
|
|
653
|
-
});
|
|
654
|
-
|
|
655
|
-
// No Sistema Principal (Pai):
|
|
656
|
-
window.addEventListener('message', (event) => {
|
|
657
|
-
if (event.data?.tipo === 'VERTICE_SALVO') {
|
|
658
|
-
console.log('Recebido do Iframe:', event.data.payload);
|
|
659
|
-
}
|
|
660
|
-
});
|
|
661
|
-
```
|
|
662
|
-
|
|
663
|
-
---
|
|
664
|
-
|
|
665
|
-
## 🧩 Catálogo de Componentes & Referência
|
|
666
|
-
|
|
667
|
-
### 🟢 Camada 1: Fundamentos
|
|
668
|
-
| Tag | Descrição | Principais Atributos / Props | Eventos Emitidos |
|
|
669
|
-
| :--- | :--- | :--- | :--- |
|
|
670
|
-
| `<ui-botao-primario>` | Botão com estados de loading, ícone e variantes. Form-associated (`type="submit"`/`"reset"`, `name`/`value`, `form`). Só com ícone, informe `aria-label` (ou `title`). | `variante`, `carregando`, `disabled`, `type`, `aria-label`, `target-modal` | `ui-click` |
|
|
671
|
-
| `<ui-campo-texto>` | Input de texto com Floating Label, validação e senha. | `label`, `value`, `tipo`, `obrigatorio`, `name` | `ui-input`, `ui-change` |
|
|
672
|
-
| `<ui-lista-flutuante>` | Select/Dropdown com Bottom Sheet no mobile. | `itens`, `value`, `placeholder`, `name` | `ui-selecionar` |
|
|
673
|
-
| `<ui-texto>` | Tipografia semântica (H1-H6, corpo, caption, código). | `variante`, `cor`, `peso` | - |
|
|
674
|
-
| `<ui-icone>` | Wrapper para ícones vetoriais padronizados. | `nome`, `tamanho`, `cor` | - |
|
|
675
|
-
|
|
676
|
-
### 🔵 Camada 2: Controles & Seleção
|
|
677
|
-
| Tag | Descrição | Principais Atributos / Props | Eventos Emitidos |
|
|
678
|
-
| :--- | :--- | :--- | :--- |
|
|
679
|
-
| `<ui-checkbox>` | Caixa de seleção múltipla com estado indeterminado. | `marcado`, `indeterminado`, `name`, `value` | `ui-change` |
|
|
680
|
-
| `<ui-radio>` | Opção única com agrupamento automático por nome. | `marcado`, `name`, `value` | `ui-change` |
|
|
681
|
-
| `<ui-switch>` | Chave de alternância liga/desliga física instantânea. | `ativo`, `name`, `value` | `ui-change` |
|
|
682
|
-
| `<ui-segmented>` | Controle segmentado de opções (Pills/Tabs deslizantes). | `opcoes`, `value`, `name`, `tamanho` | `ui-change`, `ui-selecionar` |
|
|
683
|
-
| `<ui-badge>` / `<ui-chip>` | Tags de status e chips com botão de remoção. | `variante`, `removivel`, `value` | `ui-remove` |
|
|
684
|
-
| `<ui-avatar>` | Avatar com fotos, iniciais e status online. | `nome`, `src`, `status`, `tamanho` | - |
|
|
685
|
-
|
|
686
|
-
### 🟣 Camada 3: Contêineres, Overlays, Dados & GIS
|
|
687
|
-
| Tag | Descrição | Principais Atributos / Props | Eventos Emitidos |
|
|
688
|
-
| :--- | :--- | :--- | :--- |
|
|
689
|
-
| `<ui-card>` | Cartão de conteúdo com slots nomeados e elevação. | `elevacao`, `clicavel` | `ui-click` |
|
|
690
|
-
| `<ui-modal>` | Modal centralizado no PC e Bottom Sheet no Mobile. Abrir/fechar por `abrir()`/`fechar()` ou pelo atributo `aberto` tem o mesmo efeito (eventos, foco, `inert`). Foco inicial no `[autofocus]` ou no primeiro controle do conteúdo; ao fechar, volta ao gatilho. Modais empilhados: só o último aberto é interativo. | `aberto`, `titulo`, `bottom-sheet`, `bloquear-fechamento` (oculta o "✕" e ignora Esc/fundo) | `ui-abrir`, `ui-fechar` |
|
|
691
|
-
| `<ui-drawer>` | Painel lateral deslizante (Sheet/Gaveta direita/esquerda). | `aberto`, `posicao` (`direita`, `esquerda`, `baixo`, `cima`), `titulo`, `largura` | `ui-abrir`, `ui-fechar` |
|
|
692
|
-
| `<ui-alerta>` | Banner de notificação contextual fixo. | `variante`, `titulo`, `fechavel` | `ui-fechar` |
|
|
693
|
-
| `<ui-toast>` | Notificações flutuantes inteligentes com pilha flex. | `UIToast.notificar({ tipo, mensagem })` | - |
|
|
694
|
-
| `<ui-tooltip>` | Dica contextual inteligente (Hover PC / Toque Mobile). O texto vira `aria-description` do gatilho (lido pelo leitor de tela, também repassado pelo `<ui-botao>`); **Esc** fecha sem mover o foco; o balão não some ao levar o ponteiro até ele. | `texto`, `posicao`, `gatilho` | - |
|
|
695
|
-
| `<ui-skeleton>` | Placeholder de carregamento animado com pulsos. | `tipo`, `largura`, `altura`, `animado` | - |
|
|
696
|
-
| `<ui-stat>` | Cartão KPI de estatísticas, métricas e tendências. | `rotulo`, `valor`, `variacao`, `tendencia` (`alta`, `baixa`, `neutro`) | - |
|
|
697
|
-
| `<ui-tabela>` | Tabela orientada a dados, virtualizada tipo Excel. **Teclado**: cabeçalhos ordenáveis são botões (Tab + Enter/Espaço, com `aria-sort`); nas linhas, ↑/↓, Home/End e PageUp/PageDown movem o foco e Enter/Espaço selecionam (`aria-current`). A seleção é mantida ao ordenar e filtrar. Nome acessível via `aria-label`. | `colunas`, `dados`, `src`, `densidade`, `aria-label` | `ui-sort`, `ui-column-resize`, `ui-linha-clique` |
|
|
698
|
-
| `<ui-tabela-propriedades>` | Inspetor de propriedades técnicas padrão AutoCAD & Revit com cálculos matemáticos inline (+, -, *, /, ^, %), arraste de valor contínuo (scrubbing), splitter redimensionável e editores CAD. | `categorias`, `tipo-objeto`, `splitter-pos`, `modo-aplicar`, `filtro` | `ui-propriedade-alterada`, `ui-aplicar`, `ui-desfazer`, `ui-editar-tipo`, `ui-acao-clique`, `ui-quick-select`, `ui-calculadora` |
|
|
699
|
-
| `<ui-ribbon>` | Barra de ferramentas em abas e grupos (estilo AutoCAD / Word / Excel): botões grandes e pequenos em colunas de 3, toggles, menus suspensos, abas contextuais, modo recolhido (duplo clique na aba) e navegação por teclado (roving tabindex). | `abas`, `aba-ativa`, `recolhido`, `compacto` | `ui-ferramenta`, `ui-aba-change` |
|
|
700
|
-
| `<ui-paleta-ferramentas>` | Paleta de ferramentas (estilo Illustrator / Photoshop): seleção exclusiva, grupos com flyout (clique longo, botão direito ou seta), 1 ou 2 colunas, vertical/horizontal e atalhos de teclado que percorrem o grupo. | `ferramentas`, `valor`, `orientacao`, `colunas`, `tamanho`, `atalhos` | `ui-change`, `ui-selecionar`, `ui-ferramenta` |
|
|
701
|
-
| `<ui-mapa>` | Mapa geográfico interativo com camadas OpenStreetMap. | `lat`, `lng`, `zoom`, `camadas` | - |
|
|
702
|
-
| `<ui-camadas>` | Painel de camadas vetoriais CAD/GIS com hierarquia em árvore, barra de arraste vertical (`redimensionavel`), estabilidade de altura sem colapso, drag-and-drop, métricas geodésicas e persistência no LocalStorage. | `redimensionavel`, `altura`, `min-altura`, `max-altura`, `flutuante`, `colapsado`, `camada-ativa`, `persistir` | `ui-redimensionar-altura`, `ui-camada-selecionada`, `ui-camada-visibilidade`, `ui-camadas-reordenadas`, `ui-acao-massa` |
|
|
703
|
-
| `<ui-canvas-cad>` | Mesa CAD/GIS para poligonais e vértices
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
1
|
+
# 🎨 UI Components Kit - Web Components Nativos & Universais
|
|
2
|
+
|
|
3
|
+
Biblioteca de **Web Components Nativos Universais e Agnósticos**, construída no padrão oficial **W3C Custom Elements + Shadow DOM**, com TypeScript, Design Tokens em CSS modular e Vite.
|
|
4
|
+
|
|
5
|
+
Projetada para funcionar em **qualquer linguagem, framework ou sistema web** (HTML puro, React, Next.js, Vue, Angular, Svelte, PHP, Django, WordPress, Blazor, etc.) com **zero dependências externas** (exceto `<ui-mapa>` e `<ui-canvas-cad>`, que usam o Leaflet como dependência opcional).
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## 📑 Índice
|
|
10
|
+
|
|
11
|
+
1. [Por que Web Components?](#-por-que-web-components)
|
|
12
|
+
2. [Como Importar na sua Aplicação](#-como-importar-na-sua-aplicação)
|
|
13
|
+
- [Opção 1: CDN / Script Tag (HTML puro, PHP, Django)](#opção-1-cdn--script-tag-html-puro-php-django)
|
|
14
|
+
- [Opção 2: NPM / Módulos ES (React, Vue, Next.js, Vite)](#opção-2-npm--módulos-es-react-vue-nextjs-vite)
|
|
15
|
+
3. [Como Controlar os Componentes (5 Pilares)](#-como-controlar-os-componentes-5-pilares)
|
|
16
|
+
4. [⚡ Recursos Inteligentes de Alta Produtividade](#-recursos-inteligentes-de-alta-produtividade)
|
|
17
|
+
- [Ações Declarativas "Zero-JS" (Triggers Nativos)](#1-ações-declarativas-zero-js-triggers-nativos)
|
|
18
|
+
- [Formulários Automáticos com FormData Nativo (W3C FACE)](#2-formulários-automáticos-com-formdata-nativo-w3c-face)
|
|
19
|
+
- [Barramento Global de Orquestração (UIBus)](#3-barramento-global-de-orquestração-uibus)
|
|
20
|
+
- [Tabelas Autônomas com Auto-Fetch Remoto](#4-tabelas-autônomas-com-auto-fetch-remoto)
|
|
21
|
+
5. [💻 Exemplos de Uso por Tecnologia](#-exemplos-de-uso-por-tecnologia)
|
|
22
|
+
- [HTML Puro + JavaScript](#html-puro--javascript)
|
|
23
|
+
- [React / Next.js](#react--nextjs)
|
|
24
|
+
- [Vue.js](#vuejs)
|
|
25
|
+
- [Iframes / Microfrontends](#iframes--microfrontends)
|
|
26
|
+
6. [🧩 Catálogo de Componentes & Referência](#-catálogo-de-componentes--referência)
|
|
27
|
+
7. [🛠️ Como Executar e Compilar Localmente](#️-como-executar-e-compilar-localmente)
|
|
28
|
+
|
|
29
|
+
---
|
|
30
|
+
|
|
31
|
+
## 🎯 Por que Web Components?
|
|
32
|
+
|
|
33
|
+
* 🌐 **100% Universal e Agnóstico**: Funciona em qualquer stack sem necessidade de bibliotecas intermediárias.
|
|
34
|
+
* 🛡️ **Encapsulamento Total (Shadow DOM)**: O CSS da sua aplicação nunca quebra o componente, e o CSS do componente nunca vaza para o seu site.
|
|
35
|
+
* 📐 **Design Tokens Centralizados**: Variáveis CSS personalizáveis para cores, tipografia, raios e densidade.
|
|
36
|
+
* 🚀 **Suporte a Altíssima Densidade**: Otimizado para interfaces densas e técnicas (GIS, CAD, Topografia de 15px a 20px de altura) até interfaces fluidas modernas.
|
|
37
|
+
|
|
38
|
+
---
|
|
39
|
+
|
|
40
|
+
## 📦 Como Importar na sua Aplicação
|
|
41
|
+
|
|
42
|
+
### Opção 1: CDN / Script Tag (HTML puro, PHP, Django)
|
|
43
|
+
|
|
44
|
+
Adicione as tags no `<head>` ou antes do fechamento do `</body>`:
|
|
45
|
+
|
|
46
|
+
```html
|
|
47
|
+
<!-- 1. Design Tokens e Estilos Globais -->
|
|
48
|
+
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@thibezer/ui-components-kit@1/dist/ui-kit.css">
|
|
49
|
+
|
|
50
|
+
<!-- 2. Biblioteca dos Componentes (Módulo ES) -->
|
|
51
|
+
<script type="module" src="https://cdn.jsdelivr.net/npm/@thibezer/ui-components-kit@1/dist/index.js"></script>
|
|
52
|
+
|
|
53
|
+
<!-- 3. Uso imediato no HTML -->
|
|
54
|
+
<ui-botao-primario variante="primary">Clique Aqui</ui-botao-primario>
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
> **Mapa e CAD via CDN (`<ui-mapa>`, `<ui-canvas-cad>`)**: esses componentes dependem do [Leaflet](https://leafletjs.com/), importado como `leaflet` (especificador "bare"), que o navegador só resolve com um *import map*. Declare-o **antes** do script da biblioteca:
|
|
58
|
+
>
|
|
59
|
+
> ```html
|
|
60
|
+
> <script type="importmap">
|
|
61
|
+
> { "imports": { "leaflet": "https://cdn.jsdelivr.net/npm/leaflet@1.9.4/+esm" } }
|
|
62
|
+
> </script>
|
|
63
|
+
> ```
|
|
64
|
+
>
|
|
65
|
+
> Os demais componentes não precisam do Leaflet. Com npm, basta `npm install leaflet`.
|
|
66
|
+
|
|
67
|
+
### Opção 2: NPM / Módulos ES (React, Vue, Next.js, Vite)
|
|
68
|
+
|
|
69
|
+
Instale pelo npm:
|
|
70
|
+
|
|
71
|
+
```bash
|
|
72
|
+
npm install @thibezer/ui-components-kit
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
> O pacote é publicado já compilado (`dist/`) e **não executa build na instalação**, então funciona em CI/CD e em servidores com `npm ci --omit=dev`. A antiga instalação por URL Git (`git+https://github.com/...`) não é mais suportada: o repositório não versiona `dist/`.
|
|
76
|
+
|
|
77
|
+
No ponto de entrada da sua aplicação (`main.ts`, `index.js` ou `App.tsx`):
|
|
78
|
+
|
|
79
|
+
```typescript
|
|
80
|
+
// 1. Estilos globais obrigatórios (tokens CSS)
|
|
81
|
+
import '@thibezer/ui-components-kit/style.css';
|
|
82
|
+
|
|
83
|
+
// 2. Biblioteca completa (ou escolha os submódulos abaixo)
|
|
84
|
+
import '@thibezer/ui-components-kit';
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
#### 🚀 Importação Modular e Otimizada (Sub-paths)
|
|
88
|
+
|
|
89
|
+
Pague apenas pelo que utilizar. Importe por domínio de funcionalidade ou por componente específico:
|
|
90
|
+
|
|
91
|
+
O export map expõe explicitamente os pontos de entrada canônicos (ESM em `.js`, CommonJS em `.cjs` e tipos `.d.ts`):
|
|
92
|
+
|
|
93
|
+
| Subpath | Arquivo (ESM) |
|
|
94
|
+
|---|---|
|
|
95
|
+
| `@thibezer/ui-components-kit` | `dist/index.js` |
|
|
96
|
+
| `@thibezer/ui-components-kit/camadas` | `dist/camadas.js` |
|
|
97
|
+
| `@thibezer/ui-components-kit/forms` | `dist/forms.js` |
|
|
98
|
+
| `@thibezer/ui-components-kit/feedback` | `dist/feedback.js` |
|
|
99
|
+
| `@thibezer/ui-components-kit/tabela` | `dist/tabela.js` |
|
|
100
|
+
| `@thibezer/ui-components-kit/style.css` | `dist/ui-kit.css` (100% autocontido, sem `@import`) |
|
|
101
|
+
|
|
102
|
+
##### 1. Por Domínio / Categoria:
|
|
103
|
+
```typescript
|
|
104
|
+
import '@thibezer/ui-components-kit/forms'; // Campos, Select, Checkbox, Radio, Switch (~8 kB gzip)
|
|
105
|
+
import '@thibezer/ui-components-kit/feedback'; // Modais, Drawers, Alertas, Toasts, Tooltips, Skeletons (~6 kB gzip)
|
|
106
|
+
import '@thibezer/ui-components-kit/data'; // Tabela, Tabela-Propriedades, Stat KPI, Badge (~4 kB gzip)
|
|
107
|
+
import '@thibezer/ui-components-kit/tools'; // Ribbon CAD/Office e Paleta de Ferramentas (~10 kB gzip)
|
|
108
|
+
import '@thibezer/ui-components-kit/core'; // Apenas UIBus, Zero-JS e ListenerBag (< 1 kB gzip)
|
|
109
|
+
import '@thibezer/ui-components-kit/canvas'; // Mesa CAD vetorial e motor GIS (~33 kB gzip)
|
|
110
|
+
import '@thibezer/ui-components-kit/camadas'; // Painel de Camadas GIS/CAD redimensionável (~21 kB gzip)
|
|
111
|
+
import '@thibezer/ui-components-kit/mapa'; // Mapa Geográfico Leaflet (~3 kB gzip)
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
##### 2. Granular por Componente (Ultra Leve):
|
|
115
|
+
```typescript
|
|
116
|
+
import '@thibezer/ui-components-kit/botao'; // Apenas <ui-botao> e <ui-botao-primario> (~3.4 kB gzip)
|
|
117
|
+
import '@thibezer/ui-components-kit/campo-texto'; // Apenas <ui-campo-texto> com FACE e anti-zoom (~3.9 kB gzip)
|
|
118
|
+
import '@thibezer/ui-components-kit/modal'; // Apenas <ui-modal> com bottom-sheet mobile (~3.3 kB gzip)
|
|
119
|
+
import '@thibezer/ui-components-kit/card'; // Apenas <ui-card> com elevação (~2.3 kB gzip)
|
|
120
|
+
import '@thibezer/ui-components-kit/tabela'; // Apenas <ui-tabela> virtualizada
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
> **Zero Overhead**: Uma tela que utilize apenas `<ui-botao>` e `<ui-campo-texto>` importa menos de **8 kB gzip**, sem carregar nada de Leaflet, CAD, GIS ou virtualização.
|
|
124
|
+
|
|
125
|
+
---
|
|
126
|
+
|
|
127
|
+
## 🎛️ Como Controlar os Componentes (5 Pilares)
|
|
128
|
+
|
|
129
|
+
```text
|
|
130
|
+
┌─────────────────────────────────────────────────────────────┐
|
|
131
|
+
│ SISTEMA EXTERNO │
|
|
132
|
+
└──────┬───────────────▲─────────────────┬─────────────────▲──┘
|
|
133
|
+
│ │ │ │
|
|
134
|
+
1. Atributos 4. Eventos Custom 2. Propriedades 3. Métodos
|
|
135
|
+
(HTML) (ui-*) (Objetos/Listas) (Imperativo)
|
|
136
|
+
│ │ │ │
|
|
137
|
+
┌──────▼───────────────┴─────────────────▼─────────────────┴──┐
|
|
138
|
+
│ WEB COMPONENT (<ui-*>) │
|
|
139
|
+
└─────────────────────────────────────────────────────────────┘
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
### 1. Atributos HTML (Controle Declarativo)
|
|
143
|
+
Configurações simples passadas diretamente nas tags:
|
|
144
|
+
```html
|
|
145
|
+
<ui-campo-texto label="CPF" placeholder="000.000.000-00" obrigatorio></ui-campo-texto>
|
|
146
|
+
<ui-modal id="meu-modal" titulo="Confirmar Exclusão"></ui-modal>
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
---
|
|
150
|
+
|
|
151
|
+
### 📏 Ajuste de Altura e Dimensionamento Inteligente (Zero Atrito)
|
|
152
|
+
|
|
153
|
+
Os campos de texto (`<ui-campo-texto>`), listas flutuantes/selects (`<ui-lista-flutuante>`, `<ui-select>`) e botões (`<ui-botao-primario>`) possuem 4 formas flexíveis de ajuste de altura:
|
|
154
|
+
|
|
155
|
+
#### 1. Via Atributo de Tamanho Predefinido (`tamanho` ou `densidade`):
|
|
156
|
+
```html
|
|
157
|
+
<!-- Compacto (26px) - Ideal para Toolbars CAD/GIS, tabelas e alta densidade -->
|
|
158
|
+
<ui-campo-texto tamanho="sm" placeholder="26px Compacto"></ui-campo-texto>
|
|
159
|
+
<ui-lista-flutuante tamanho="sm" placeholder="Selecione..."></ui-lista-flutuante>
|
|
160
|
+
|
|
161
|
+
<!-- Padrão (34px) - Padrão moderno e equilibrado para formulários e modais -->
|
|
162
|
+
<ui-campo-texto tamanho="md" placeholder="34px Padrão"></ui-campo-texto>
|
|
163
|
+
<ui-lista-flutuante tamanho="md" placeholder="Selecione..."></ui-lista-flutuante>
|
|
164
|
+
|
|
165
|
+
<!-- Conforto / Touch (42px) - Otimizado para dispositivos móveis e telas sensíveis ao toque -->
|
|
166
|
+
<ui-campo-texto tamanho="lg" placeholder="42px Conforto"></ui-campo-texto>
|
|
167
|
+
<ui-lista-flutuante tamanho="lg" placeholder="Selecione..."></ui-lista-flutuante>
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
#### 2. Via Atributo de Altura Explícita (`altura` ou `height`):
|
|
171
|
+
```html
|
|
172
|
+
<!-- Define a altura exata em pixels diretamente no elemento -->
|
|
173
|
+
<ui-campo-texto altura="38" placeholder="Altura de 38px"></ui-campo-texto>
|
|
174
|
+
<ui-lista-flutuante altura="44px" placeholder="Altura de 44px"></ui-lista-flutuante>
|
|
175
|
+
<ui-botao-primario altura="40">Salvar</ui-botao-primario>
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
#### 3. Via Variável CSS Customizável (`--ui-campo-altura`):
|
|
179
|
+
```css
|
|
180
|
+
/* No seu CSS global ou no container pai */
|
|
181
|
+
.meu-formulario {
|
|
182
|
+
--ui-campo-altura: 36px; /* Aplica instantaneamente em todos os inputs, selects e botões filhos */
|
|
183
|
+
}
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
#### 4. Via Barramento Global de Densidade (`UIBus`):
|
|
187
|
+
```javascript
|
|
188
|
+
import { UIBus } from '@thibezer/ui-components-kit';
|
|
189
|
+
|
|
190
|
+
// Altera a densidade de toda a aplicação em tempo real:
|
|
191
|
+
UIBus.definirDensidade('compacta'); // 26px
|
|
192
|
+
UIBus.definirDensidade('padrao'); // 34px
|
|
193
|
+
UIBus.definirDensidade('relaxada'); // 42px
|
|
194
|
+
UIBus.definirDensidade(38); // Valor numérico em px customizado
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
---
|
|
198
|
+
|
|
199
|
+
### 2. Propriedades JavaScript (Dados Complexos)
|
|
200
|
+
Para enviar arrays e objetos complexos:
|
|
201
|
+
```javascript
|
|
202
|
+
const tabela = document.querySelector('ui-tabela');
|
|
203
|
+
tabela.colunas = [
|
|
204
|
+
{ id: 'ponto', rotulo: 'Ponto', ordenavel: true },
|
|
205
|
+
{ id: 'altitude', rotulo: 'Altitude (m)' }
|
|
206
|
+
];
|
|
207
|
+
tabela.dados = [
|
|
208
|
+
{ ponto: 'P-01', altitude: '542,15' },
|
|
209
|
+
{ ponto: 'P-02', altitude: '545,30' }
|
|
210
|
+
];
|
|
211
|
+
```
|
|
212
|
+
|
|
213
|
+
### 3. Métodos Imperativos (Ações Diretas)
|
|
214
|
+
Comandos diretos chamados na instância do elemento:
|
|
215
|
+
```javascript
|
|
216
|
+
const modal = document.getElementById('meu-modal');
|
|
217
|
+
modal.abrir();
|
|
218
|
+
modal.fechar();
|
|
219
|
+
```
|
|
220
|
+
|
|
221
|
+
### 4. Eventos Customizados Nativos (`ui-*`)
|
|
222
|
+
Escuta de eventos disparados pelas interações do usuário:
|
|
223
|
+
```javascript
|
|
224
|
+
const campo = document.querySelector('ui-campo-texto');
|
|
225
|
+
campo.addEventListener('ui-input', (e) => {
|
|
226
|
+
console.log('Texto digitado:', e.detail.value);
|
|
227
|
+
});
|
|
228
|
+
```
|
|
229
|
+
|
|
230
|
+
> **Mutação de usuário vs. programática (`<ui-camadas>`)**: eventos saem do componente **somente** em resposta a interações físicas (clique, drag-and-drop, teclado). Atribuir `painel.layers = [...]`, alterar atributos (`camada-ativa`, `colapsado`, `mapa-base-ativo`...) ou chamar métodos públicos (`definirCamadaAtiva`, `selecionarFeicao`, `limparSelecao`, `colapsar`, `definirAltura`...) apenas atualiza o DOM interno — sem redisparar eventos. Isso elimina loops de sincronização em apps reativos (React, Vue, Svelte). Para forçar a emissão numa chamada programática, passe `emitirEvento = true` (ex.: `painel.definirCamadaAtiva('lotes', true)`).
|
|
231
|
+
|
|
232
|
+
### 5. Serviços Globais e Helpers
|
|
233
|
+
Utilitários prontos para uso sem necessidade de instanciar elementos:
|
|
234
|
+
```javascript
|
|
235
|
+
import { UIToast, UIBus } from '@thibezer/ui-components-kit';
|
|
236
|
+
|
|
237
|
+
UIToast.notificar({
|
|
238
|
+
tipo: 'sucesso',
|
|
239
|
+
titulo: 'Registro Salvo!',
|
|
240
|
+
mensagem: 'Os dados foram sincronizados.',
|
|
241
|
+
duracao: 4000
|
|
242
|
+
});
|
|
243
|
+
```
|
|
244
|
+
|
|
245
|
+
### 6. Escala de Elevação (z-index)
|
|
246
|
+
Todos os componentes flutuantes consomem tokens de elevação previsíveis (com fallback), definidos em `ui-kit.css`. Sobrescreva-os no `:root` da aplicação para encaixar a pilha do kit entre os HUDs e modais do seu app:
|
|
247
|
+
```css
|
|
248
|
+
:root {
|
|
249
|
+
--ui-z-workspace-hud: 500; /* <ui-camadas flutuante>, <ui-seletor-mapa-base>, toolbars do canvas */
|
|
250
|
+
--ui-z-docked-bar: 600; /* <ui-ribbon> recolhido, <ui-tabela-propriedades flutuante> */
|
|
251
|
+
--ui-z-drawer: 700; /* <ui-drawer> e backdrop */
|
|
252
|
+
--ui-z-modal: 1000; /* <ui-modal> e backdrop */
|
|
253
|
+
--ui-z-popover: 1050; /* menus suspensos/contexto, <ui-select> (acima do modal, funciona dentro dele) */
|
|
254
|
+
--ui-z-toast: 1100; /* UIToast */
|
|
255
|
+
--ui-z-tooltip: 1200; /* <ui-tooltip> */
|
|
256
|
+
}
|
|
257
|
+
```
|
|
258
|
+
|
|
259
|
+
### 7. Acessibilidade Nativa de Rótulos
|
|
260
|
+
`<ui-input>` (alias de `<ui-campo-texto>`), `<ui-select>` e `<ui-switch>` geram IDs únicos internamente e associam o rótulo visível ao controle nativo do Shadow DOM — o projeto consumidor não precisa gerenciar IDs:
|
|
261
|
+
```html
|
|
262
|
+
<ui-input label="Nome"></ui-input> <!-- <label for> ↔ <input> interno -->
|
|
263
|
+
<ui-select label="Cidade">...</ui-select> <!-- aria-labelledby = rótulo + valor atual -->
|
|
264
|
+
<ui-switch label="Modo escuro"></ui-switch> <!-- role="switch" aria-labelledby -->
|
|
265
|
+
|
|
266
|
+
<!-- Sem o atributo label, o nome acessível vem de fora do Shadow DOM: -->
|
|
267
|
+
<label>Telefone <ui-input></ui-input></label>
|
|
268
|
+
<ui-switch aria-label="Camada visível"></ui-switch>
|
|
269
|
+
```
|
|
270
|
+
|
|
271
|
+
### 8. Temas Claro e Escuro
|
|
272
|
+
Sem configuração, o kit **segue o tema do sistema operacional** (`prefers-color-scheme`). Para fixar um tema, use o atributo na raiz — ou em qualquer elemento, para fixar só aquele trecho:
|
|
273
|
+
```html
|
|
274
|
+
<html data-tema="escuro"> <!-- ou "claro"; também aceitos: class="dark|light" e data-theme="dark|light" -->
|
|
275
|
+
<aside data-tema="claro">…</aside> <!-- trecho claro dentro de uma página escura -->
|
|
276
|
+
```
|
|
277
|
+
```javascript
|
|
278
|
+
UIBus.definirTema('auto'); // volta a seguir o SO
|
|
279
|
+
UIBus.on('tema:alterado', ({ tema }) => { /* também dispara quando o SO muda, se o tema não estiver fixado */ });
|
|
280
|
+
```
|
|
281
|
+
Os componentes recebem o tema **apenas pelos tokens de cor** (`--ui-cor-*`, `--ui-sombra-*`), que atravessam o Shadow DOM. Todo token de texto atinge contraste **WCAG AA (4,5:1)** nos dois temas, inclusive sobre fundos tingidos de status e no texto sobre a cor primária e o botão destrutivo — verificado em `tests/tema.test.ts`.
|
|
282
|
+
|
|
283
|
+
| Token | Uso |
|
|
284
|
+
| :--- | :--- |
|
|
285
|
+
| `--ui-cor-texto-sucesso` / `-erro` / `-alerta` / `-info` | Texto e tons de status (alertas, badges, toasts) |
|
|
286
|
+
| `--ui-cor-texto-sobre-status` | Texto sobre fundo sólido de status (badge sólido) |
|
|
287
|
+
| `--ui-cor-fundo-recuado` | Faixas rebaixadas (rodapés de modal e drawer) |
|
|
288
|
+
| `--ui-sombra-sm` / `-md` / `-lg` | Sombras: densas no escuro, suaves no claro |
|
|
289
|
+
|
|
290
|
+
### 9. Tipografia e Raios
|
|
291
|
+
Todos os componentes usam apenas dois tokens de família de fonte e uma escala de raios derivada de `--ui-raio-borda`. Sobrescreva no `:root` (a escala é calculada lá):
|
|
292
|
+
```css
|
|
293
|
+
:root {
|
|
294
|
+
--ui-fonte-base: 'Roboto', sans-serif; /* textos da interface */
|
|
295
|
+
--ui-fonte-codigo: 'JetBrains Mono', monospace; /* coordenadas, valores técnicos, código */
|
|
296
|
+
|
|
297
|
+
--ui-raio-borda: 4px; /* base: botões, campos, menus */
|
|
298
|
+
/* derivados automaticamente: --ui-raio-sm (2/3), --ui-raio-lg (5/3), --ui-raio-xl (8/3) */
|
|
299
|
+
/* --ui-raio-borda: 0 → interface totalmente reta */
|
|
300
|
+
}
|
|
301
|
+
```
|
|
302
|
+
|
|
303
|
+
### 10. Estilização Interna com `::part`
|
|
304
|
+
O Shadow DOM isola o CSS, mas os elementos internos principais são expostos com `part`, com nomes consistentes entre componentes (uma regra serve para vários):
|
|
305
|
+
|
|
306
|
+
| Componente | Parts |
|
|
307
|
+
| :--- | :--- |
|
|
308
|
+
| `<ui-botao>` / `<ui-botao-primario>` | `base`, `spinner` |
|
|
309
|
+
| `<ui-campo-texto>` / `<ui-input>` | `rotulo`, `campo`, `input`, `icone`, `icone-esquerda`, `icone-direita`, `ajuda` |
|
|
310
|
+
| `<ui-lista-flutuante>` / `<ui-select>` | `rotulo`, `campo`, `valor`, `seta`, `lista`, `opcao`, `opcao-selecionada` |
|
|
311
|
+
| `<ui-checkbox>`, `<ui-radio>`, `<ui-switch>` | `base`, `controle`, `indicador`, `rotulo` |
|
|
312
|
+
| `<ui-segmented>` | `base`, `indicador`, `opcao`, `opcao-selecionada` |
|
|
313
|
+
| `<ui-modal>`, `<ui-drawer>` | `fundo`, `painel`, `cabecalho`, `titulo`, `descricao` (drawer), `fechar`, `corpo`, `rodape` |
|
|
314
|
+
| `<ui-card>` | `base`, `midia`, `cabecalho`, `corpo`, `rodape` |
|
|
315
|
+
| `<ui-badge>` / `<ui-chip>` | `base`, `rotulo`, `remover` |
|
|
316
|
+
| `<ui-alerta>` / toasts | `base`, `icone`, `conteudo`, `titulo`, `mensagem`, `acao`, `fechar`, `progresso` |
|
|
317
|
+
| `<ui-tooltip>` | `balao`, `texto`, `seta` |
|
|
318
|
+
| `<ui-tabela>` | `base`, `tabela`, `celula-cabecalho`, `ordenar`, `linha`, `linha-selecionada`, `celula`, `vazio`, `carregando` |
|
|
319
|
+
|
|
320
|
+
```css
|
|
321
|
+
ui-campo-texto::part(campo) { border-width: 2px; }
|
|
322
|
+
ui-modal::part(painel) { max-width: 720px; }
|
|
323
|
+
ui-tabela::part(linha-selecionada) { background: #0b3d2a; }
|
|
324
|
+
:is(ui-checkbox, ui-radio, ui-switch)::part(rotulo) { font-weight: 600; }
|
|
325
|
+
```
|
|
326
|
+
|
|
327
|
+
---
|
|
328
|
+
|
|
329
|
+
## ⚡ Recursos Inteligentes de Alta Produtividade
|
|
330
|
+
|
|
331
|
+
### 1. Ações Declarativas "Zero-JS" (Triggers Nativos)
|
|
332
|
+
Você pode acionar modais, fechar janelas, disparar notificações toast ou copiar textos **sem escrever nenhuma linha de JavaScript**, apenas adicionando atributos nas tags HTML:
|
|
333
|
+
|
|
334
|
+
```html
|
|
335
|
+
<!-- Abrir Modal sem JS -->
|
|
336
|
+
<ui-botao-primario target-modal="modal-exclusao" variante="destrutivo">
|
|
337
|
+
Excluir Registro
|
|
338
|
+
</ui-botao-primario>
|
|
339
|
+
|
|
340
|
+
<!-- Modal com Fechamento e Toast automáticos -->
|
|
341
|
+
<ui-modal id="modal-exclusao" titulo="Confirmação">
|
|
342
|
+
Tem certeza que deseja excluir?
|
|
343
|
+
<div slot="rodape">
|
|
344
|
+
<ui-botao-primario dismiss-modal variante="secundario">Cancelar</ui-botao-primario>
|
|
345
|
+
<ui-botao-primario dismiss-modal toast-sucesso="Excluído com sucesso!" variante="destrutivo">
|
|
346
|
+
Confirmar
|
|
347
|
+
</ui-botao-primario>
|
|
348
|
+
</div>
|
|
349
|
+
</ui-modal>
|
|
350
|
+
|
|
351
|
+
<!-- Copiar Texto em 1 Clique -->
|
|
352
|
+
<ui-campo-texto id="input-token" value="SIGEF-2026-X88"></ui-campo-texto>
|
|
353
|
+
<ui-botao-primario copiar-texto="#input-token" copiar-mensagem="Token copiado!">
|
|
354
|
+
Copiar Chave
|
|
355
|
+
</ui-botao-primario>
|
|
356
|
+
```
|
|
357
|
+
|
|
358
|
+
#### Tabela de Atributos Zero-JS Disponíveis:
|
|
359
|
+
| Atributo | Descrição | Exemplo de Uso |
|
|
360
|
+
| :--- | :--- | :--- |
|
|
361
|
+
| `target-modal="id"` | Abre o modal com o ID especificado ao clicar. | `target-modal="modal-login"` |
|
|
362
|
+
| `dismiss-modal` | Fecha o modal atual (ou o especificado por ID). | `dismiss-modal` |
|
|
363
|
+
| `toast-sucesso="msg"` | Dispara uma notificação flutuante de sucesso. | `toast-sucesso="Salvo com sucesso!"` |
|
|
364
|
+
| `toast-erro="msg"` | Dispara uma notificação flutuante de erro. | `toast-erro="Falha na conexão."` |
|
|
365
|
+
| `toast-alerta="msg"` | Dispara uma notificação flutuante de aviso. | `toast-alerta="Preencha os campos obrigatórios."` |
|
|
366
|
+
| `copiar-texto="texto\|#id"` | Copia o texto ou o valor do elemento referenciado. | `copiar-texto="#campo-pix"` |
|
|
367
|
+
| `limpar-form="id"` | Reseta todos os campos do formulário indicado. | `limpar-form="form-cadastro"` |
|
|
368
|
+
| `alternar-tema` | Alterna entre tema claro e escuro globalmente (a partir do tema em vigor, inclusive o do SO). | `alternar-tema` |
|
|
369
|
+
|
|
370
|
+
---
|
|
371
|
+
|
|
372
|
+
### 2. Formulários Automáticos com `FormData` Nativo (W3C FACE)
|
|
373
|
+
Todos os campos (`<ui-campo-texto>`, `<ui-lista-flutuante>`, `<ui-checkbox>`, `<ui-radio>`, `<ui-switch>`) implementam a especificação oficial de **Form-Associated Custom Elements**.
|
|
374
|
+
|
|
375
|
+
Isso significa que você extrai os dados de todos os campos de uma única vez, sem ler um por um:
|
|
376
|
+
|
|
377
|
+
```html
|
|
378
|
+
<form id="form-imovel">
|
|
379
|
+
<ui-campo-texto name="denominacao" label="Nome da Fazenda" value="Boa Vista"></ui-campo-texto>
|
|
380
|
+
<ui-campo-texto name="municipio" label="Município" value="Uberlândia"></ui-campo-texto>
|
|
381
|
+
<ui-checkbox name="georreferenciado" label="Georreferenciado" marcado value="sim"></ui-checkbox>
|
|
382
|
+
|
|
383
|
+
<ui-botao-primario type="submit">Salvar Imóvel</ui-botao-primario>
|
|
384
|
+
</form>
|
|
385
|
+
```
|
|
386
|
+
|
|
387
|
+
```javascript
|
|
388
|
+
const form = document.getElementById('form-imovel');
|
|
389
|
+
|
|
390
|
+
form.addEventListener('submit', (e) => {
|
|
391
|
+
e.preventDefault();
|
|
392
|
+
|
|
393
|
+
// Extrai TODOS os campos em 1 única linha nativa:
|
|
394
|
+
const dados = Object.fromEntries(new FormData(form));
|
|
395
|
+
console.log(dados);
|
|
396
|
+
// Resultado: { denominacao: "Boa Vista", municipio: "Uberlândia", georreferenciado: "sim" }
|
|
397
|
+
});
|
|
398
|
+
```
|
|
399
|
+
|
|
400
|
+
Assim como nos campos nativos, **Enter** em um `<ui-campo-texto>` submete o formulário pelo botão de envio padrão (`<ui-botao-primario type="submit">` ou `<button>`), que também pode estar fora do `<form>` com `form="id-do-form"`. Para impedir, chame `preventDefault()` no `keydown`. O `name`/`value` do botão que submeteu chega como `e.submitter` (use `new FormData(form, e.submitter)`), e gatilhos Zero-JS em botões `disabled` ou `carregando` são ignorados.
|
|
401
|
+
|
|
402
|
+
---
|
|
403
|
+
|
|
404
|
+
### 3. Barramento Global de Orquestração (`UIBus`)
|
|
405
|
+
O `UIBus` é uma central reativa que permite comandar qualquer componente do sistema ou ouvir eventos sem precisar de `querySelector`:
|
|
406
|
+
|
|
407
|
+
```javascript
|
|
408
|
+
import { UIBus } from '@thibezer/ui-components-kit';
|
|
409
|
+
|
|
410
|
+
// 1. Executar Ações Diretas:
|
|
411
|
+
UIBus.abrirModal('modal-confirmacao');
|
|
412
|
+
UIBus.fecharModal('modal-confirmacao');
|
|
413
|
+
UIBus.notificar({ tipo: 'sucesso', mensagem: 'Operação concluída!' });
|
|
414
|
+
UIBus.copiar('Texto para a área de transferência', 'Copiado!');
|
|
415
|
+
UIBus.definirDensidade('compacta'); // 'compacta' | 'normal' | 'relaxada'
|
|
416
|
+
UIBus.definirTema('escuro'); // 'claro' | 'escuro' | 'auto' (segue o SO); sem argumento, alterna
|
|
417
|
+
UIBus.obterTema(); // tema em vigor: 'claro' | 'escuro'
|
|
418
|
+
|
|
419
|
+
// 2. Comunicação Desacoplada (Pub/Sub):
|
|
420
|
+
UIBus.on('vertice:selecionado', (dadosVertice) => {
|
|
421
|
+
console.log('Vértice selecionado em qualquer tela:', dadosVertice);
|
|
422
|
+
});
|
|
423
|
+
|
|
424
|
+
UIBus.emit('vertice:selecionado', { id: 101, nome: 'M-01', altitude: 432.10 });
|
|
425
|
+
```
|
|
426
|
+
|
|
427
|
+
---
|
|
428
|
+
|
|
429
|
+
### 4. Tabelas Autônomas com Auto-Fetch Remoto
|
|
430
|
+
A `<ui-tabela>` pode buscar dados de uma API remota de forma totalmente autônoma, exibindo indicador de loading, tratando erros e permitindo filtragem instantânea:
|
|
431
|
+
|
|
432
|
+
```html
|
|
433
|
+
<ui-tabela
|
|
434
|
+
id="tabela-vertices"
|
|
435
|
+
src="/api/v1/geodesia/vertices"
|
|
436
|
+
max-height="400px"
|
|
437
|
+
densidade="compacta">
|
|
438
|
+
</ui-tabela>
|
|
439
|
+
```
|
|
440
|
+
|
|
441
|
+
```javascript
|
|
442
|
+
const tabela = document.getElementById('tabela-vertices');
|
|
443
|
+
|
|
444
|
+
// Definir colunas da tabela:
|
|
445
|
+
tabela.colunas = [
|
|
446
|
+
{ id: 'nome_vertice', rotulo: 'Vértice', ordenavel: true },
|
|
447
|
+
{ id: 'este', rotulo: 'Este (m)', ordenavel: true, alinhamento: 'direita' },
|
|
448
|
+
{ id: 'norte', rotulo: 'Norte (m)', ordenavel: true, alinhamento: 'direita' }
|
|
449
|
+
];
|
|
450
|
+
|
|
451
|
+
// Métodos inteligentes disponíveis na tabela:
|
|
452
|
+
tabela.filtrar('M-01'); // Filtra instantaneamente em todas as colunas
|
|
453
|
+
tabela.recarregar(); // Recarrega os dados da API remota
|
|
454
|
+
```
|
|
455
|
+
|
|
456
|
+
---
|
|
457
|
+
|
|
458
|
+
## 💻 Exemplos de Uso por Tecnologia
|
|
459
|
+
|
|
460
|
+
### HTML Puro + JavaScript
|
|
461
|
+
```html
|
|
462
|
+
<!DOCTYPE html>
|
|
463
|
+
<html lang="pt-BR">
|
|
464
|
+
<head>
|
|
465
|
+
<link rel="stylesheet" href="dist/ui-kit.css">
|
|
466
|
+
<script type="module" src="dist/index.js"></script>
|
|
467
|
+
</head>
|
|
468
|
+
<body>
|
|
469
|
+
<ui-campo-texto id="meu-campo" label="Nome do Projeto"></ui-campo-texto>
|
|
470
|
+
<ui-botao-primario target-modal="meu-modal">Abrir Detalhes</ui-botao-primario>
|
|
471
|
+
|
|
472
|
+
<ui-modal id="meu-modal" titulo="Detalhes">
|
|
473
|
+
<p>Conteúdo do modal...</p>
|
|
474
|
+
<div slot="rodape">
|
|
475
|
+
<ui-botao-primario dismiss-modal>Fechar</ui-botao-primario>
|
|
476
|
+
</div>
|
|
477
|
+
</ui-modal>
|
|
478
|
+
|
|
479
|
+
<script>
|
|
480
|
+
document.getElementById('meu-campo').addEventListener('ui-input', (e) => {
|
|
481
|
+
console.log('Digitado:', e.detail.value);
|
|
482
|
+
});
|
|
483
|
+
</script>
|
|
484
|
+
</body>
|
|
485
|
+
</html>
|
|
486
|
+
```
|
|
487
|
+
|
|
488
|
+
---
|
|
489
|
+
|
|
490
|
+
### React / Next.js (SSR & Client Components)
|
|
491
|
+
|
|
492
|
+
A biblioteca é **100% SSR-safe**: todas as classes herdam de `SafeHTMLElement` e o registro de tags utiliza verificações de segurança para ambientes sem DOM (Node.js). Isso garante que você pode importar tipos, classes e constantes tanto no servidor quanto no cliente sem encontrar `ReferenceError: HTMLElement is not defined` ou `customElements is not defined`.
|
|
493
|
+
|
|
494
|
+
#### Tipos no TSX (autocompletar e checagem)
|
|
495
|
+
O pacote gera tipos para todas as tags a partir do Custom Elements Manifest. Registre-os uma vez no `tsconfig.json`:
|
|
496
|
+
|
|
497
|
+
```json
|
|
498
|
+
{ "compilerOptions": { "types": ["@thibezer/ui-components-kit/tipos-react"] } }
|
|
499
|
+
```
|
|
500
|
+
|
|
501
|
+
A partir daí o editor sugere atributos, propriedades e eventos de cada tag, e o TypeScript recusa valores inválidos:
|
|
502
|
+
|
|
503
|
+
```tsx
|
|
504
|
+
<ui-tabela
|
|
505
|
+
colunas={[{ id: 'ponto', rotulo: 'Ponto', ordenavel: true }]} // tipado como TabelaColuna[]
|
|
506
|
+
densidade="compacta" // 'compacta' | 'normal' | 'relaxada'
|
|
507
|
+
onui-sort={(e) => console.log(e.detail)} // eventos ui-* no formato do React 19
|
|
508
|
+
/>
|
|
509
|
+
<ui-tabela densidade="enorme" /> // ❌ erro de tipo
|
|
510
|
+
```
|
|
511
|
+
|
|
512
|
+
Outros JSX (Preact, Solid etc.) podem usar o mapa agnóstico `ElementosUI` de `@thibezer/ui-components-kit/tipos-elementos`.
|
|
513
|
+
|
|
514
|
+
#### No Next.js (App Router):
|
|
515
|
+
|
|
516
|
+
Crie um componente cliente provedor ou registre no topo do seu layout/página cliente:
|
|
517
|
+
|
|
518
|
+
```tsx
|
|
519
|
+
// components/UIProvider.tsx
|
|
520
|
+
'use client';
|
|
521
|
+
|
|
522
|
+
import { useEffect } from 'react';
|
|
523
|
+
import '@thibezer/ui-components-kit/style.css';
|
|
524
|
+
import '@thibezer/ui-components-kit/register'; // Registra todos os Custom Elements com segurança no cliente
|
|
525
|
+
|
|
526
|
+
export function UIProvider({ children }: { children: React.ReactNode }) {
|
|
527
|
+
return <>{children}</>;
|
|
528
|
+
}
|
|
529
|
+
```
|
|
530
|
+
|
|
531
|
+
Ou registre de forma modular apenas o que a tela precisa:
|
|
532
|
+
|
|
533
|
+
```tsx
|
|
534
|
+
// app/dashboard/page.tsx
|
|
535
|
+
'use client';
|
|
536
|
+
|
|
537
|
+
import React, { useEffect, useRef, useState } from 'react';
|
|
538
|
+
import '@thibezer/ui-components-kit/style.css';
|
|
539
|
+
import '@thibezer/ui-components-kit/forms';
|
|
540
|
+
import '@thibezer/ui-components-kit/botao';
|
|
541
|
+
import '@thibezer/ui-components-kit/tabela';
|
|
542
|
+
import { UIBus } from '@thibezer/ui-components-kit/core';
|
|
543
|
+
import type { UITabela } from '@thibezer/ui-components-kit/tabela';
|
|
544
|
+
|
|
545
|
+
export default function DashboardPropriedades() {
|
|
546
|
+
const tabelaRef = useRef<UITabela>(null);
|
|
547
|
+
const [nome, setNome] = useState('');
|
|
548
|
+
|
|
549
|
+
useEffect(() => {
|
|
550
|
+
if (tabelaRef.current) {
|
|
551
|
+
tabelaRef.current.colunas = [
|
|
552
|
+
{ id: 'id', rotulo: 'Código' },
|
|
553
|
+
{ id: 'nome', rotulo: 'Propriedade' }
|
|
554
|
+
];
|
|
555
|
+
tabelaRef.current.dados = [
|
|
556
|
+
{ id: 1, nome: 'Fazenda Santa Luzia' }
|
|
557
|
+
];
|
|
558
|
+
}
|
|
559
|
+
}, []);
|
|
560
|
+
|
|
561
|
+
return (
|
|
562
|
+
<div style={{ padding: 24 }}>
|
|
563
|
+
<ui-campo-texto
|
|
564
|
+
label="Pesquisar Imóvel"
|
|
565
|
+
value={nome}
|
|
566
|
+
onInput={(e: any) => {
|
|
567
|
+
// Os eventos nativos `input`/`change` não têm `detail`: leia o valor do próprio elemento
|
|
568
|
+
const valor = e.target.value;
|
|
569
|
+
setNome(valor);
|
|
570
|
+
tabelaRef.current?.filtrar(valor);
|
|
571
|
+
}}
|
|
572
|
+
></ui-campo-texto>
|
|
573
|
+
|
|
574
|
+
<ui-tabela ref={tabelaRef} max-height="300px" densidade="compacta"></ui-tabela>
|
|
575
|
+
|
|
576
|
+
<ui-botao-primario
|
|
577
|
+
variante="primary"
|
|
578
|
+
onClick={() => UIBus.notificar({ tipo: 'sucesso', mensagem: 'Dados sincronizados!' })}>
|
|
579
|
+
Sincronizar
|
|
580
|
+
</ui-botao-primario>
|
|
581
|
+
</div>
|
|
582
|
+
);
|
|
583
|
+
}
|
|
584
|
+
```
|
|
585
|
+
|
|
586
|
+
---
|
|
587
|
+
|
|
588
|
+
### Vue.js
|
|
589
|
+
|
|
590
|
+
Para autocompletar e checar props e eventos nos templates (Volar), registre os tipos no `tsconfig.json` e informe ao Vue que tags `ui-*` são custom elements:
|
|
591
|
+
|
|
592
|
+
```json
|
|
593
|
+
{ "compilerOptions": { "types": ["@thibezer/ui-components-kit/tipos-vue"] } }
|
|
594
|
+
```
|
|
595
|
+
|
|
596
|
+
```javascript
|
|
597
|
+
// vite.config.js
|
|
598
|
+
vue({ template: { compilerOptions: { isCustomElement: (tag) => tag.startsWith('ui-') } } })
|
|
599
|
+
```
|
|
600
|
+
|
|
601
|
+
```vue
|
|
602
|
+
<template>
|
|
603
|
+
<div class="container">
|
|
604
|
+
<ui-campo-texto
|
|
605
|
+
:value="termoBusca"
|
|
606
|
+
label="Buscar Vértice"
|
|
607
|
+
@ui-input="aoDigitar"
|
|
608
|
+
/>
|
|
609
|
+
|
|
610
|
+
<ui-lista-flutuante
|
|
611
|
+
.itens="opcoes"
|
|
612
|
+
@ui-selecionar="aoSelecionar"
|
|
613
|
+
/>
|
|
614
|
+
|
|
615
|
+
<ui-botao-primario target-modal="modal-confirmacao">
|
|
616
|
+
Confirmar Operação
|
|
617
|
+
</ui-botao-primario>
|
|
618
|
+
</div>
|
|
619
|
+
</template>
|
|
620
|
+
|
|
621
|
+
<script setup>
|
|
622
|
+
import { ref } from 'vue';
|
|
623
|
+
import '@thibezer/ui-components-kit/style.css';
|
|
624
|
+
import '@thibezer/ui-components-kit';
|
|
625
|
+
|
|
626
|
+
const termoBusca = ref('');
|
|
627
|
+
const opcoes = ref([
|
|
628
|
+
{ id: '1', label: 'Marco Geodésico M' },
|
|
629
|
+
{ id: '2', label: 'Ponto Topográfico P' }
|
|
630
|
+
]);
|
|
631
|
+
|
|
632
|
+
function aoDigitar(e) {
|
|
633
|
+
termoBusca.value = e.detail.value;
|
|
634
|
+
}
|
|
635
|
+
|
|
636
|
+
function aoSelecionar(e) {
|
|
637
|
+
console.log('Opção selecionada:', e.detail);
|
|
638
|
+
}
|
|
639
|
+
</script>
|
|
640
|
+
```
|
|
641
|
+
|
|
642
|
+
---
|
|
643
|
+
|
|
644
|
+
### Iframes / Microfrontends
|
|
645
|
+
Comunicação segura entre iframes e sistemas pais via eventos do `UIBus`:
|
|
646
|
+
|
|
647
|
+
```javascript
|
|
648
|
+
// Dentro do Iframe (Filho):
|
|
649
|
+
import { UIBus } from '@thibezer/ui-components-kit';
|
|
650
|
+
|
|
651
|
+
UIBus.on('vertice:salvo', (dados) => {
|
|
652
|
+
window.parent.postMessage({ tipo: 'VERTICE_SALVO', payload: dados }, '*');
|
|
653
|
+
});
|
|
654
|
+
|
|
655
|
+
// No Sistema Principal (Pai):
|
|
656
|
+
window.addEventListener('message', (event) => {
|
|
657
|
+
if (event.data?.tipo === 'VERTICE_SALVO') {
|
|
658
|
+
console.log('Recebido do Iframe:', event.data.payload);
|
|
659
|
+
}
|
|
660
|
+
});
|
|
661
|
+
```
|
|
662
|
+
|
|
663
|
+
---
|
|
664
|
+
|
|
665
|
+
## 🧩 Catálogo de Componentes & Referência
|
|
666
|
+
|
|
667
|
+
### 🟢 Camada 1: Fundamentos
|
|
668
|
+
| Tag | Descrição | Principais Atributos / Props | Eventos Emitidos |
|
|
669
|
+
| :--- | :--- | :--- | :--- |
|
|
670
|
+
| `<ui-botao-primario>` | Botão com estados de loading, ícone e variantes. Form-associated (`type="submit"`/`"reset"`, `name`/`value`, `form`). Só com ícone, informe `aria-label` (ou `title`). | `variante`, `carregando`, `disabled`, `type`, `aria-label`, `target-modal` | `ui-click` |
|
|
671
|
+
| `<ui-campo-texto>` | Input de texto com Floating Label, validação e senha. | `label`, `value`, `tipo`, `obrigatorio`, `name` | `ui-input`, `ui-change` |
|
|
672
|
+
| `<ui-lista-flutuante>` | Select/Dropdown com Bottom Sheet no mobile. | `itens`, `value`, `placeholder`, `name` | `ui-selecionar` |
|
|
673
|
+
| `<ui-texto>` | Tipografia semântica (H1-H6, corpo, caption, código). | `variante`, `cor`, `peso` | - |
|
|
674
|
+
| `<ui-icone>` | Wrapper para ícones vetoriais padronizados. | `nome`, `tamanho`, `cor` | - |
|
|
675
|
+
|
|
676
|
+
### 🔵 Camada 2: Controles & Seleção
|
|
677
|
+
| Tag | Descrição | Principais Atributos / Props | Eventos Emitidos |
|
|
678
|
+
| :--- | :--- | :--- | :--- |
|
|
679
|
+
| `<ui-checkbox>` | Caixa de seleção múltipla com estado indeterminado. | `marcado`, `indeterminado`, `name`, `value` | `ui-change` |
|
|
680
|
+
| `<ui-radio>` | Opção única com agrupamento automático por nome. | `marcado`, `name`, `value` | `ui-change` |
|
|
681
|
+
| `<ui-switch>` | Chave de alternância liga/desliga física instantânea. | `ativo`, `name`, `value` | `ui-change` |
|
|
682
|
+
| `<ui-segmented>` | Controle segmentado de opções (Pills/Tabs deslizantes). | `opcoes`, `value`, `name`, `tamanho` | `ui-change`, `ui-selecionar` |
|
|
683
|
+
| `<ui-badge>` / `<ui-chip>` | Tags de status e chips com botão de remoção. | `variante`, `removivel`, `value` | `ui-remove` |
|
|
684
|
+
| `<ui-avatar>` | Avatar com fotos, iniciais e status online. | `nome`, `src`, `status`, `tamanho` | - |
|
|
685
|
+
|
|
686
|
+
### 🟣 Camada 3: Contêineres, Overlays, Dados & GIS
|
|
687
|
+
| Tag | Descrição | Principais Atributos / Props | Eventos Emitidos |
|
|
688
|
+
| :--- | :--- | :--- | :--- |
|
|
689
|
+
| `<ui-card>` | Cartão de conteúdo com slots nomeados e elevação. | `elevacao`, `clicavel` | `ui-click` |
|
|
690
|
+
| `<ui-modal>` | Modal centralizado no PC e Bottom Sheet no Mobile. Abrir/fechar por `abrir()`/`fechar()` ou pelo atributo `aberto` tem o mesmo efeito (eventos, foco, `inert`). Foco inicial no `[autofocus]` ou no primeiro controle do conteúdo; ao fechar, volta ao gatilho. Modais empilhados: só o último aberto é interativo. | `aberto`, `titulo`, `bottom-sheet`, `bloquear-fechamento` (oculta o "✕" e ignora Esc/fundo) | `ui-abrir`, `ui-fechar` |
|
|
691
|
+
| `<ui-drawer>` | Painel lateral deslizante (Sheet/Gaveta direita/esquerda). | `aberto`, `posicao` (`direita`, `esquerda`, `baixo`, `cima`), `titulo`, `largura` | `ui-abrir`, `ui-fechar` |
|
|
692
|
+
| `<ui-alerta>` | Banner de notificação contextual fixo. | `variante`, `titulo`, `fechavel` | `ui-fechar` |
|
|
693
|
+
| `<ui-toast>` | Notificações flutuantes inteligentes com pilha flex. | `UIToast.notificar({ tipo, mensagem })` | - |
|
|
694
|
+
| `<ui-tooltip>` | Dica contextual inteligente (Hover PC / Toque Mobile). O texto vira `aria-description` do gatilho (lido pelo leitor de tela, também repassado pelo `<ui-botao>`); **Esc** fecha sem mover o foco; o balão não some ao levar o ponteiro até ele. | `texto`, `posicao`, `gatilho` | - |
|
|
695
|
+
| `<ui-skeleton>` | Placeholder de carregamento animado com pulsos. | `tipo`, `largura`, `altura`, `animado` | - |
|
|
696
|
+
| `<ui-stat>` | Cartão KPI de estatísticas, métricas e tendências. | `rotulo`, `valor`, `variacao`, `tendencia` (`alta`, `baixa`, `neutro`) | - |
|
|
697
|
+
| `<ui-tabela>` | Tabela orientada a dados, virtualizada tipo Excel. **Teclado**: cabeçalhos ordenáveis são botões (Tab + Enter/Espaço, com `aria-sort`); nas linhas, ↑/↓, Home/End e PageUp/PageDown movem o foco e Enter/Espaço selecionam (`aria-current`). A seleção é mantida ao ordenar e filtrar. Nome acessível via `aria-label`. | `colunas`, `dados`, `src`, `densidade`, `aria-label` | `ui-sort`, `ui-column-resize`, `ui-linha-clique` |
|
|
698
|
+
| `<ui-tabela-propriedades>` | Inspetor de propriedades técnicas padrão AutoCAD & Revit com cálculos matemáticos inline (+, -, *, /, ^, %), arraste de valor contínuo (scrubbing), splitter redimensionável e editores CAD. | `categorias`, `tipo-objeto`, `splitter-pos`, `modo-aplicar`, `filtro` | `ui-propriedade-alterada`, `ui-aplicar`, `ui-desfazer`, `ui-editar-tipo`, `ui-acao-clique`, `ui-quick-select`, `ui-calculadora` |
|
|
699
|
+
| `<ui-ribbon>` | Barra de ferramentas em abas e grupos (estilo AutoCAD / Word / Excel): botões grandes e pequenos em colunas de 3, toggles, menus suspensos, abas contextuais, modo recolhido (duplo clique na aba) e navegação por teclado (roving tabindex). | `abas`, `aba-ativa`, `recolhido`, `compacto` | `ui-ferramenta`, `ui-aba-change` |
|
|
700
|
+
| `<ui-paleta-ferramentas>` | Paleta de ferramentas (estilo Illustrator / Photoshop): seleção exclusiva, grupos com flyout (clique longo, botão direito ou seta), 1 ou 2 colunas, vertical/horizontal e atalhos de teclado que percorrem o grupo. | `ferramentas`, `valor`, `orientacao`, `colunas`, `tamanho`, `atalhos` | `ui-change`, `ui-selecionar`, `ui-ferramenta` |
|
|
701
|
+
| `<ui-mapa>` | Mapa geográfico interativo com camadas OpenStreetMap. | `lat`, `lng`, `zoom`, `camadas` | - |
|
|
702
|
+
| `<ui-camadas>` | Painel de camadas vetoriais CAD/GIS com hierarquia em árvore, barra de arraste vertical (`redimensionavel`), estabilidade de altura sem colapso, drag-and-drop, métricas geodésicas e persistência no LocalStorage. | `redimensionavel`, `altura`, `min-altura`, `max-altura`, `flutuante`, `colapsado`, `camada-ativa`, `persistir` | `ui-redimensionar-altura`, `ui-camada-selecionada`, `ui-camada-visibilidade`, `ui-camadas-reordenadas`, `ui-acao-massa` |
|
|
703
|
+
| `<ui-canvas-cad>` | Mesa CAD/GIS para poligonais, vértices geodésicos e **feições genéricas** (ponto, linha, polígono, círculo, texto) que você cria: seleção por clique e caixa, popup, edição de vértices, snap, 15 ferramentas de desenho/medição, oficial × prévia, cursores remotos e culling/clusters para 100 mil feições. Linha multiparte, feição `oculta`, selo de texto e contorno de ponto. Nenhuma camada vem pronta. Guia: [`docs/guia-migracao-mapengine.md`](docs/guia-migracao-mapengine.md). | `pontos`, `segmentos`, `ferramentas`, `sem-camadas-padrao`, `sem-painel-camadas`, `sem-barra-rapida`, `sem-atalho-snap`, `aceitar-origem`, `inicializarAgora()`, `definirFeicoes()`, `aplicarLote()`, `definirFerramenta()`, `editarVertices()`, `definirMargensHud()`, `definirEstilosExternos()`, `fitBounds()` | `ui-ponto-selecionado`, `cad-selecao`, `cad-feicao-selecionada`, `cad-feicao-criada`, `cad-feicao-atualizada`, `cad-feicao-hover`, `cad-feicao-menu`, `cad-snap`, `cad-previas` e outros (ver `docs/canvas-cad-eventos.md`) |
|
|
704
|
+
|
|
705
|
+
#### `<ui-canvas-cad>`: montar só com API pública (2.1)
|
|
706
|
+
|
|
707
|
+
```html
|
|
708
|
+
<ui-canvas-cad id="mesa" sem-camadas-padrao sem-painel-camadas sem-barra-rapida sem-atalho-snap aceitar-origem></ui-canvas-cad>
|
|
709
|
+
```
|
|
710
|
+
```js
|
|
711
|
+
const mapa = mesa.inicializarAgora(); // L.Map síncrono (idempotente; nunca cria um 2º mapa)
|
|
712
|
+
mesa.definirEstilosExternos([...document.styleSheets]); // CSS do app dentro do shadow root (string ou folhas)
|
|
713
|
+
mesa.definirMargensHud({ base: 56, direita: 320 }); // HUDs de desenho/edição fora de barras e painéis
|
|
714
|
+
mesa.aplicarLote('glebas', { adicionar, atualizar, remover }); // uma regravação, ordem preservada
|
|
715
|
+
mesa.atualizarFeicao('glebas', 'g1', { propriedades }, { substituirPropriedades: true });
|
|
716
|
+
mesa.definirOpcoesPopup({ copiarParaAreaDeTransferencia: false });
|
|
717
|
+
```
|
|
718
|
+
|
|
719
|
+
- Camadas de fábrica (satélite, SIGEF, homologados, perímetro, vizinhos, vértices, grade) só somem com `sem-camadas-padrao`; sem
|
|
720
|
+
o atributo continuam como sempre.
|
|
721
|
+
- `Feicao.oculta` (não desenha nem seleciona, mas existe) ≠ `Feicao.excluida`. Linha multiparte: `geometria.partes`.
|
|
722
|
+
- Tudo, com exemplos: [`docs/guia-migracao-mapengine.md`](docs/guia-migracao-mapengine.md) · eventos e ordem das ferramentas:
|
|
723
|
+
[`docs/canvas-cad-eventos.md`](docs/canvas-cad-eventos.md) · números de desempenho: [`docs/desempenho-feicoes.md`](docs/desempenho-feicoes.md).
|
|
724
|
+
|
|
725
|
+
|
|
726
|
+
---
|
|
727
|
+
|
|
728
|
+
### Custom Elements Manifest
|
|
729
|
+
O pacote publica `custom-elements.json` (campo `customElements` do `package.json`), o formato padrão que IDEs, Storybook e geradores de documentação leem para listar tags, atributos, propriedades, eventos e `::part` de cada componente. Ele é gerado no `npm run build` pelo [`@custom-elements-manifest/analyzer`](https://custom-elements-manifest.open-wc.org/), e os tipos React/Vue são derivados dele — por isso nunca ficam desatualizados em relação ao código.
|
|
730
|
+
|
|
731
|
+
---
|
|
732
|
+
|
|
733
|
+
## 🛠️ Como Executar e Compilar Localmente
|
|
734
|
+
|
|
735
|
+
1. **Instalar Dependências**:
|
|
736
|
+
```bash
|
|
737
|
+
npm install
|
|
738
|
+
```
|
|
739
|
+
|
|
740
|
+
2. **Executar o Playground Sandbox em Desenvolvimento**:
|
|
741
|
+
```bash
|
|
742
|
+
npm run dev
|
|
743
|
+
```
|
|
744
|
+
Acesse: `http://localhost:5173/`
|
|
745
|
+
|
|
746
|
+
3. **Compilar Pacote de Produção (Library Mode)**:
|
|
747
|
+
```bash
|
|
748
|
+
npm run build
|
|
749
|
+
```
|
|
750
|
+
Gera na pasta `dist/`:
|
|
751
|
+
* `dist/index.js` e `dist/<modulo>.js` (Módulos ES para Vite, Webpack, Rollup)
|
|
752
|
+
* `dist/index.cjs` e `dist/<modulo>.cjs` (CommonJS para `require`)
|
|
753
|
+
* `dist/*.d.ts` (Tipagens TypeScript)
|
|
754
|
+
* `dist/ui-kit.css` (Design Tokens compilados, 100% autocontido — o build falha se restar qualquer `@import`)
|
|
755
|
+
* `dist/custom-elements.json` (Custom Elements Manifest) e `dist/tipos-react.d.ts`, `dist/tipos-vue.d.ts`, `dist/tipos-elementos.d.ts`
|
|
756
|
+
|
|
757
|
+
4. **Verificar os tipos gerados** (depois do build):
|
|
758
|
+
```bash
|
|
759
|
+
npm run test:tipos
|
|
760
|
+
```
|