vex-ui-kit 1.0.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.
Files changed (44) hide show
  1. package/README.md +830 -0
  2. package/dist/adapters/react.cjs.js +17 -0
  3. package/dist/adapters/react.cjs.js.map +1 -0
  4. package/dist/adapters/react.d.mts +37 -0
  5. package/dist/adapters/react.d.ts +37 -0
  6. package/dist/adapters/react.esm.js +17 -0
  7. package/dist/adapters/react.esm.js.map +1 -0
  8. package/dist/adapters/react.umd.js +63 -0
  9. package/dist/adapters/react.umd.js.map +1 -0
  10. package/dist/adapters/svelte.cjs.js +17 -0
  11. package/dist/adapters/svelte.cjs.js.map +1 -0
  12. package/dist/adapters/svelte.d.mts +21 -0
  13. package/dist/adapters/svelte.d.ts +21 -0
  14. package/dist/adapters/svelte.esm.js +17 -0
  15. package/dist/adapters/svelte.esm.js.map +1 -0
  16. package/dist/adapters/svelte.umd.js +44 -0
  17. package/dist/adapters/svelte.umd.js.map +1 -0
  18. package/dist/adapters/vue.cjs.js +17 -0
  19. package/dist/adapters/vue.cjs.js.map +1 -0
  20. package/dist/adapters/vue.d.mts +35 -0
  21. package/dist/adapters/vue.d.ts +35 -0
  22. package/dist/adapters/vue.esm.js +17 -0
  23. package/dist/adapters/vue.esm.js.map +1 -0
  24. package/dist/adapters/vue.umd.js +147 -0
  25. package/dist/adapters/vue.umd.js.map +1 -0
  26. package/dist/index-CpFq7Lxe.d.mts +213 -0
  27. package/dist/index-CpFq7Lxe.d.ts +213 -0
  28. package/dist/themes/flat.css +47 -0
  29. package/dist/themes/glass.css +22 -0
  30. package/dist/themes/minimal.css +35 -0
  31. package/dist/themes/neon.css +45 -0
  32. package/dist/themes/outline.css +18 -0
  33. package/dist/themes/pastel.css +21 -0
  34. package/dist/themes/tokens.css +329 -0
  35. package/dist/vex-ui-kit.css +329 -0
  36. package/dist/vexui.cjs.js +17 -0
  37. package/dist/vexui.cjs.js.map +1 -0
  38. package/dist/vexui.d.mts +1 -0
  39. package/dist/vexui.d.ts +1 -0
  40. package/dist/vexui.esm.js +17 -0
  41. package/dist/vexui.esm.js.map +1 -0
  42. package/dist/vexui.umd.js +17 -0
  43. package/dist/vexui.umd.js.map +1 -0
  44. package/package.json +63 -0
package/README.md ADDED
@@ -0,0 +1,830 @@
1
+ <div align="center">
2
+
3
+ # VexUI
4
+
5
+ **Sistema completo de feedback visual para a web**
6
+
7
+ Alerts · Modals · Drawers · Step Flows · Inline Prompts
8
+
9
+ [![npm version](https://img.shields.io/badge/npm-v1.0.0-4F46E5?style=flat-square)](https://npmjs.com/package/vexui)
10
+ [![license](https://img.shields.io/badge/license-MIT-22c55e?style=flat-square)](./LICENSE)
11
+ [![zero deps](https://img.shields.io/badge/deps-zero-06B6D4?style=flat-square)](#)
12
+ [![gzip](https://img.shields.io/badge/gzip-~8kb-f59e0b?style=flat-square)](#)
13
+
14
+ ```bash
15
+ npm install vex-ui-kit
16
+ ```
17
+
18
+ </div>
19
+
20
+ ---
21
+
22
+ ## Índice
23
+
24
+ - [Visão Geral](#visão-geral)
25
+ - [Por que VexUI?](#por-que-vexui)
26
+ - [Tecnologias](#tecnologias)
27
+ - [Instalação](#instalação)
28
+ - [Estrutura de Arquivos](#estrutura-de-arquivos)
29
+ - [Alerts](#alerts)
30
+ - [Modals](#modals)
31
+ - [Funcionalidades Exclusivas](#funcionalidades-exclusivas)
32
+ - [Sistema de Temas](#sistema-de-temas)
33
+ - [Acessibilidade](#acessibilidade)
34
+ - [Integrações](#integrações)
35
+ - [API Completa](#api-completa)
36
+ - [Roadmap](#roadmap)
37
+
38
+ ---
39
+
40
+ ## Visão Geral
41
+
42
+ VexUI é uma biblioteca JavaScript de **feedback visual** que substitui completamente soluções fragmentadas — sem precisar de uma lib para toast, outra para modal e outra para drawer. Com uma única instalação e API unificada, você tem acesso a um sistema coeso de comunicação com o usuário.
43
+
44
+ Os componentes se comportam como **banners visuais ricos** — inspirados nos Alerts do Bootstrap, mas com glassmorphism, animações polidas, suporte a ações, filas de prioridade e muito mais.
45
+
46
+ ```js
47
+ import vex from 'vexui'
48
+
49
+ // Simples assim
50
+ vex.alert.success('Arquivo salvo com sucesso!')
51
+
52
+ // Ou com async/await
53
+ const ok = await vex.modal.confirm({ title: 'Excluir projeto?', type: 'danger' })
54
+ if (ok) await deleteProject(id)
55
+ ```
56
+
57
+ ---
58
+
59
+ ## Por que VexUI?
60
+
61
+ | Funcionalidade | VexUI | Concorrentes |
62
+ |---|---|---|
63
+ | Alerts inline + fixed | ✅ Ambos, API única | Geralmente só um |
64
+ | Modals Promise-based | ✅ `await` nativo | Callbacks / eventos |
65
+ | Step Flow (wizard) | ✅ Built-in | ❌ Não existe |
66
+ | Drawer / Side Panel | ✅ Built-in | ❌ Não existe |
67
+ | Inline Prompt | ✅ Built-in | ❌ Não existe |
68
+ | Alert ancorado a elemento | ✅ Built-in | ❌ Não existe |
69
+ | Alert atualizável em tempo real | ✅ Built-in | ❌ Não existe |
70
+ | Fila de prioridade | ✅ Built-in | ❌ Não existe |
71
+ | Histórico de notificações | ✅ Built-in | ❌ Não existe |
72
+ | Glassmorphism nativo | ✅ Padrão | ❌ Estilo genérico |
73
+ | Dark / Light automático | ✅ `prefers-color-scheme` | ⚠️ Manual / limitado |
74
+ | Theming por CSS tokens | ✅ 100% tokens | ⚠️ Parcial |
75
+ | ARIA / Acessibilidade | ✅ Completo | ⚠️ Básico / ausente |
76
+ | Zero dependências | ✅ Pure JS | ⚠️ Variado |
77
+
78
+ ---
79
+
80
+ ## Tecnologias
81
+
82
+ ### Core
83
+
84
+ | Tecnologia | Versão | Uso |
85
+ |---|---|---|
86
+ | **JavaScript (ES2020+)** | — | Engine principal da biblioteca |
87
+ | **CSS Custom Properties** | — | Sistema de tokens e temas |
88
+ | **Web Animations API** | — | Animações performáticas |
89
+ | **CSS `backdrop-filter`** | — | Efeito glassmorphism |
90
+ | **`prefers-color-scheme`** | — | Dark/light mode automático |
91
+ | **`prefers-reduced-motion`** | — | Respeito às preferências de acessibilidade |
92
+ | **ARIA / WAI-ARIA 1.2** | — | Acessibilidade completa |
93
+
94
+ ### Build & Tooling
95
+
96
+ | Ferramenta | Uso |
97
+ |---|---|
98
+ | **tsup** | Build e bundling (ESM, CJS, UMD) |
99
+ | **TypeScript** | Tipos e declarações `.d.ts` |
100
+ | **Vitest** | Testes unitários |
101
+ | **Playwright** | Testes de integração / E2E |
102
+ | **Changesets** | Versionamento semântico |
103
+ | **np** | Publicação no npm |
104
+
105
+ ### Adapters (opcionais)
106
+
107
+ | Adapter | Tecnologia |
108
+ |---|---|
109
+ | `vexui/react` | React 18+ (hook) |
110
+ | `vex-ui-kit/vue` | Vue 3 (plugin + composable) |
111
+ | `vex-ui-kit/svelte` | Svelte (store) |
112
+
113
+ > **Zero dependências no core.** Os adapters para frameworks são opcionais e separados.
114
+
115
+ ---
116
+
117
+ ## Instalação
118
+
119
+ ```bash
120
+ # npm
121
+ npm install vexui
122
+
123
+ # yarn
124
+ yarn add vexui
125
+
126
+ # pnpm
127
+ pnpm add vexui
128
+ ```
129
+
130
+ ### Via CDN (sem instalação)
131
+
132
+ ```html
133
+ <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/vexui/dist/vexui.css">
134
+ <script src="https://cdn.jsdelivr.net/npm/vexui/dist/vexui.umd.js"></script>
135
+
136
+ <script>
137
+ VexUI.alert.success('Funciona em qualquer projeto!')
138
+ </script>
139
+ ```
140
+
141
+ ### Importação no projeto
142
+
143
+ ```js
144
+ // ES Modules (recomendado)
145
+ import vex from 'vexui'
146
+ import 'vexui/dist/vexui.css'
147
+
148
+ // CommonJS
149
+ const vex = require('vexui')
150
+ ```
151
+
152
+ ---
153
+
154
+ ## Estrutura de Arquivos
155
+
156
+ ```
157
+ vexui/
158
+
159
+ ├── src/ # Código-fonte
160
+ │ │
161
+ │ ├── core/ # Engine principal (zero deps)
162
+ │ │ ├── alert.js # Sistema de alerts
163
+ │ │ ├── modal.js # Sistema de modals
164
+ │ │ ├── drawer.js # Drawer / painel lateral
165
+ │ │ ├── flow.js # Step Flow (wizard)
166
+ │ │ ├── queue.js # Fila de prioridade
167
+ │ │ ├── history.js # Histórico de notificações
168
+ │ │ ├── theme.js # Gerenciador de temas
169
+ │ │ ├── a11y.js # Utilitários de acessibilidade
170
+ │ │ └── index.js # Entry point — exporta `vex`
171
+ │ │
172
+ │ ├── themes/ # Temas prontos (CSS)
173
+ │ │ ├── tokens.css # CSS custom properties base
174
+ │ │ ├── glass.css # Glassmorphism (padrão)
175
+ │ │ ├── flat.css # Flat design
176
+ │ │ ├── outline.css # Apenas bordas
177
+ │ │ ├── minimal.css # Ultra-discreto
178
+ │ │ ├── neon.css # Neon / cyberpunk
179
+ │ │ └── pastel.css # Soft / tons pastel
180
+ │ │
181
+ │ └── adapters/ # Integrações com frameworks
182
+ │ ├── react.js # useVex() hook
183
+ │ ├── vue.js # $vex plugin + useVex()
184
+ │ └── svelte.js # vex store
185
+
186
+ ├── dist/ # Build gerado (não editar)
187
+ │ ├── vexui.esm.js # ES Modules
188
+ │ ├── vexui.cjs.js # CommonJS
189
+ │ ├── vexui.umd.js # CDN / UMD (global VexUI)
190
+ │ └── vexui.css # Estilos compilados
191
+
192
+ ├── types/
193
+ │ └── index.d.ts # TypeScript declarations
194
+
195
+ ├── tests/
196
+ │ ├── unit/ # Testes unitários (Vitest)
197
+ │ └── e2e/ # Testes E2E (Playwright)
198
+
199
+ ├── docs/ # Documentação
200
+ │ └── README.md
201
+
202
+ ├── package.json
203
+ ├── tsup.config.ts # Config de build
204
+ ├── tsconfig.json
205
+ └── LICENSE
206
+ ```
207
+
208
+ ---
209
+
210
+ ## Alerts
211
+
212
+ O sistema de alerts é o núcleo da VexUI. Diferente de toasts que aparecem em cantos flutuantes, os alerts da VexUI são **banners ricos** — inline no fluxo da página ou fixos na viewport.
213
+
214
+ ### Tipos disponíveis
215
+
216
+ ```js
217
+ vex.alert.success('Salvo com sucesso!')
218
+ vex.alert.error('Falha ao conectar com o servidor')
219
+ vex.alert.warning('Sessão expirando em 5 minutos')
220
+ vex.alert.info('Nova atualização disponível')
221
+ vex.alert.neutral('Rascunho salvo automaticamente')
222
+ vex.alert.loading('Enviando arquivo...') // com spinner animado
223
+ ```
224
+
225
+ ### Modos de posicionamento
226
+
227
+ #### Inline — renderizado no DOM
228
+
229
+ ```js
230
+ // Dentro de um container específico
231
+ vex.alert.inline('#meu-formulario', {
232
+ type: 'error',
233
+ title: 'Erro de validação',
234
+ message: 'Preencha todos os campos obrigatórios.',
235
+ })
236
+ ```
237
+
238
+ #### Fixed — flutua na viewport
239
+
240
+ ```js
241
+ // Topo da tela
242
+ vex.alert.fixed({ position: 'top', type: 'success', message: 'Deploy finalizado!' })
243
+
244
+ // Rodapé da tela
245
+ vex.alert.fixed({ position: 'bottom', type: 'info', message: '2 novas mensagens.' })
246
+ ```
247
+
248
+ #### Attached — ancorado a um elemento *(exclusivo)*
249
+
250
+ ```js
251
+ // Aparece colado ao elemento, como um popover rico
252
+ vex.alert.attach('#campo-senha', {
253
+ type: 'warning',
254
+ message: 'Senha fraca: use pelo menos 8 caracteres.',
255
+ placement: 'bottom', // top | bottom | left | right | auto
256
+ duration: 0,
257
+ })
258
+ ```
259
+
260
+ ### Alerts com botões de ação
261
+
262
+ ```js
263
+ vex.alert.warning('Você tem alterações não salvas.', {
264
+ duration: 0,
265
+ actions: [
266
+ {
267
+ label: 'Salvar agora',
268
+ variant: 'primary',
269
+ onClick: (close) => { save(); close() }
270
+ },
271
+ {
272
+ label: 'Descartar',
273
+ variant: 'danger',
274
+ onClick: (close) => { discard(); close() }
275
+ },
276
+ ]
277
+ })
278
+ ```
279
+
280
+ ### Alert de Loading atualizável *(exclusivo)*
281
+
282
+ ```js
283
+ // Cria o alert e recebe um ID
284
+ const id = vex.alert.loading('Enviando arquivo...')
285
+
286
+ // Atualiza em tempo real conforme o processo avança
287
+ vex.update(id, { message: 'Processando (45%)...' })
288
+ vex.update(id, { message: 'Processando (90%)...' })
289
+
290
+ // Transforma em sucesso ao finalizar
291
+ vex.update(id, { type: 'success', message: 'Arquivo enviado com sucesso!' })
292
+ ```
293
+
294
+ ### Alert de Upload com progresso *(exclusivo)*
295
+
296
+ ```js
297
+ const id = vex.alert.upload('Enviando documento.pdf', { total: file.size })
298
+
299
+ upload.onprogress = (e) => {
300
+ vex.progress(id, { loaded: e.loaded, total: e.total })
301
+ // Exibe: "Enviando... 4.2 MB / 10 MB · ~8s restantes"
302
+ }
303
+
304
+ upload.onload = () => {
305
+ vex.update(id, { type: 'success', message: 'Upload concluído!' })
306
+ }
307
+ ```
308
+
309
+ ### Fila de prioridade *(exclusivo)*
310
+
311
+ ```js
312
+ // Alerts críticos entram imediatamente, deslocando os demais
313
+ vex.alert.error('Servidor fora do ar', { priority: 'critical' })
314
+
315
+ // Prioridade alta — entra na frente da fila
316
+ vex.alert.warning('Sessão expirando', { priority: 'high' })
317
+
318
+ // Prioridade baixa — só aparece quando a fila esvazia
319
+ vex.alert.info('Dica do dia', { priority: 'low' })
320
+ ```
321
+
322
+ ### Todas as opções de Alert
323
+
324
+ | Opção | Tipo | Padrão | Descrição |
325
+ |---|---|---|---|
326
+ | `type` | `string` | `'info'` | `success` · `error` · `warning` · `info` · `neutral` · `loading` |
327
+ | `message` | `string` | — | Texto principal do alert |
328
+ | `title` | `string` | `null` | Título em negrito acima da mensagem |
329
+ | `duration` | `number` | `6000` | Tempo em ms. `0` = permanente |
330
+ | `dismissible` | `boolean` | `true` | Botão × para fechar manualmente |
331
+ | `icon` | `string \| null` | `auto` | Emoji, SVG string ou `null` para remover |
332
+ | `progress` | `boolean` | `true` | Barra de progresso animada do tempo restante |
333
+ | `actions` | `Action[]` | `[]` | Botões de ação dentro do alert |
334
+ | `priority` | `string` | `'normal'` | `critical` · `high` · `normal` · `low` |
335
+ | `position` | `string` | `'top'` | `top` · `bottom` — apenas para fixed |
336
+ | `align` | `string` | `'center'` | `center` · `left` · `right` |
337
+ | `animate` | `string` | `'slide'` | `slide` · `fade` · `scale` · `bounce` |
338
+ | `maxStack` | `number` | `5` | Máximo de alerts simultâneos |
339
+ | `theme` | `object` | preset | Sobrescreve tokens visuais desta instância |
340
+ | `onClose` | `function` | `null` | Callback chamado ao fechar |
341
+
342
+ ---
343
+
344
+ ## Modals
345
+
346
+ Todos os modals são **Promise-based** — retornam dados diretamente via `await`, eliminando callbacks aninhados.
347
+
348
+ ### Modal de Confirmação
349
+
350
+ ```js
351
+ const ok = await vex.modal.confirm({
352
+ type: 'danger', // danger | warning | info
353
+ title: 'Excluir projeto?',
354
+ message: 'Esta ação não pode ser desfeita. Todos os dados serão removidos permanentemente.',
355
+ confirmLabel: 'Sim, excluir',
356
+ cancelLabel: 'Cancelar',
357
+ confirmDelay: 3000, // botão bloqueado por 3s (segurança extra)
358
+ })
359
+
360
+ if (ok) await deleteProject(id)
361
+ ```
362
+
363
+ ### Modal de Aviso / Informação
364
+
365
+ ```js
366
+ await vex.modal.alert({
367
+ type: 'info',
368
+ title: 'Nova política de privacidade',
369
+ message: 'Atualizamos nossos termos em Janeiro de 2025...',
370
+ confirmLabel: 'Entendido',
371
+ })
372
+ ```
373
+
374
+ ### Modal de Formulário
375
+
376
+ ```js
377
+ const data = await vex.modal.form({
378
+ title: 'Convidar membro',
379
+ submitLabel: 'Enviar convite',
380
+ fields: [
381
+ { name: 'name', label: 'Nome completo', type: 'text', required: true },
382
+ { name: 'email', label: 'E-mail', type: 'email', required: true },
383
+ { name: 'role', label: 'Função', type: 'select', options: ['Admin', 'Editor', 'Viewer'] },
384
+ { name: 'msg', label: 'Mensagem', type: 'textarea', optional: true },
385
+ ],
386
+ validate: (data) => {
387
+ if (!data.email.includes('@empresa.com'))
388
+ return { email: 'Use seu e-mail corporativo' }
389
+ }
390
+ })
391
+
392
+ if (data) await inviteMember(data)
393
+ ```
394
+
395
+ **Tipos de campo suportados:**
396
+
397
+ | Tipo | Descrição |
398
+ |---|---|
399
+ | `text`, `email`, `password`, `number`, `url`, `tel` | Inputs nativos |
400
+ | `textarea` | Texto multilinha |
401
+ | `select` | Dropdown |
402
+ | `radio` | Grupo de opções exclusivas |
403
+ | `checkbox` | Múltipla seleção |
404
+ | `date`, `time`, `datetime-local` | Seletores de data/hora |
405
+ | `file` | Upload com preview |
406
+ | `range` | Slider numérico com label de valor |
407
+ | `color` | Seletor de cor nativo |
408
+
409
+ ### Modal de Prompt
410
+
411
+ ```js
412
+ const nome = await vex.modal.prompt({
413
+ title: 'Renomear arquivo',
414
+ placeholder: 'Ex: relatorio-final.pdf',
415
+ defaultValue: 'relatorio.pdf',
416
+ validate: (v) => v.trim().length < 3 ? 'Nome muito curto' : null
417
+ })
418
+
419
+ if (nome) await renameFile(nome)
420
+ ```
421
+
422
+ ### Modal de Preview de Mídia
423
+
424
+ ```js
425
+ vex.modal.preview({
426
+ src: '/uploads/foto.jpg',
427
+ title: 'Foto do Produto',
428
+ meta: ['PNG · 4K', '3.8 MB', 'Jan 2025'],
429
+ zoom: true,
430
+ gallery: ['/img1.jpg', '/img2.jpg', '/img3.jpg'], // navegação entre imagens
431
+ actions: [
432
+ { label: '⬇ Download', onClick: () => downloadFile() }
433
+ ],
434
+ })
435
+ ```
436
+
437
+ ### Modal Customizado
438
+
439
+ ```js
440
+ // Conteúdo completamente livre
441
+ const { close } = vex.modal.custom({
442
+ title: 'Editor avançado',
443
+ content: document.getElementById('meu-editor'), // elemento DOM ou HTML string
444
+ width: 800,
445
+ footer: false,
446
+ })
447
+ ```
448
+
449
+ ### Opções comuns a todos os Modals
450
+
451
+ | Opção | Tipo | Padrão | Descrição |
452
+ |---|---|---|---|
453
+ | `title` | `string` | — | Título do modal |
454
+ | `type` | `string` | `'info'` | `danger` · `warning` · `info` · `success` |
455
+ | `width` | `number` | `480` | Largura máxima em pixels |
456
+ | `closeOnBackdrop` | `boolean` | `true` | Fecha ao clicar no backdrop |
457
+ | `closeOnEscape` | `boolean` | `true` | Fecha ao pressionar Escape |
458
+ | `showClose` | `boolean` | `true` | Botão × no canto superior direito |
459
+ | `animate` | `string` | `'scale'` | `scale` · `slide` · `fade` |
460
+ | `scrollLock` | `boolean` | `true` | Bloqueia scroll do body enquanto aberto |
461
+ | `stackable` | `boolean` | `true` | Permite múltiplos modals sobrepostos |
462
+ | `zIndex` | `number` | `9500` | z-index do backdrop |
463
+ | `onOpen` | `function` | `null` | Callback ao abrir |
464
+ | `onClose` | `function` | `null` | Callback ao fechar |
465
+
466
+ ---
467
+
468
+ ## Funcionalidades Exclusivas
469
+
470
+ ### Step Flow — Wizard multi-etapa *(exclusivo)*
471
+
472
+ Fluxo guiado de múltiplas etapas dentro de um único modal. Cada etapa pode ter formulário próprio, validação e lógica condicional. Retorna todos os dados ao final.
473
+
474
+ ```js
475
+ const result = await vex.flow([
476
+ {
477
+ title: 'Bem-vindo!',
478
+ type: 'info',
479
+ description: 'Vamos configurar sua conta em 3 passos simples.',
480
+ },
481
+ {
482
+ title: 'Seus dados',
483
+ fields: [
484
+ { name: 'name', label: 'Nome', type: 'text', required: true },
485
+ { name: 'email', label: 'E-mail', type: 'email', required: true },
486
+ ],
487
+ // Valida antes de avançar
488
+ beforeNext: async (data) => {
489
+ const exists = await checkEmail(data.email)
490
+ if (exists) return { email: 'E-mail já cadastrado' }
491
+ }
492
+ },
493
+ {
494
+ title: 'Escolha seu plano',
495
+ fields: [
496
+ {
497
+ name: 'plan',
498
+ type: 'radio',
499
+ options: ['Starter (grátis)', 'Pro (R$49/mês)', 'Enterprise']
500
+ }
501
+ ]
502
+ },
503
+ // Etapa condicional — só aparece se escolheu Enterprise
504
+ {
505
+ title: 'Dados da empresa',
506
+ condition: (data) => data.plan === 'Enterprise',
507
+ fields: [
508
+ { name: 'company', label: 'Nome da empresa', type: 'text', required: true },
509
+ { name: 'cnpj', label: 'CNPJ', type: 'text' },
510
+ ]
511
+ },
512
+ {
513
+ title: 'Tudo pronto! 🎉',
514
+ type: 'success',
515
+ description: 'Sua conta foi configurada com sucesso.',
516
+ },
517
+ ])
518
+
519
+ // result = { name, email, plan, company?, cnpj? }
520
+ if (result) await createAccount(result)
521
+ ```
522
+
523
+ **Funcionalidades do Step Flow:**
524
+ - Barra de progresso visual com número da etapa atual
525
+ - Navegação para frente e para trás livremente
526
+ - Validação por etapa — não avança com erros
527
+ - Dados acumulados e disponíveis em todas as etapas
528
+ - Etapas condicionais baseadas em dados anteriores
529
+ - `beforeNext()` para lógica assíncrona por etapa
530
+
531
+ ---
532
+
533
+ ### Drawer — Painel lateral *(exclusivo)*
534
+
535
+ Painel deslizante que emerge da lateral sem bloquear a página. Ideal para filtros, formulários longos, detalhes de item e configurações.
536
+
537
+ ```js
538
+ const { close } = vex.drawer({
539
+ title: 'Filtros avançados',
540
+ position: 'right', // right | left | top | bottom
541
+ width: 420, // para right/left (height para top/bottom)
542
+ content: '#filtros-form', // seletor CSS ou elemento DOM
543
+ persistent: false, // fecha ao clicar fora
544
+ footer: [
545
+ { label: 'Aplicar filtros', variant: 'primary', onClick: () => { apply(); close() } },
546
+ { label: 'Limpar tudo', onClick: () => clearAll() },
547
+ ],
548
+ })
549
+ ```
550
+
551
+ ---
552
+
553
+ ### Inline Prompt — Edição contextual *(exclusivo)*
554
+
555
+ Substitui um elemento de texto por um input diretamente no DOM, sem abrir modal. Perfeito para edição inline de títulos e valores.
556
+
557
+ ```js
558
+ // O elemento #titulo vira um <input> na hora
559
+ const novoNome = await vex.prompt.inline('#titulo-projeto', {
560
+ placeholder: 'Nome do projeto',
561
+ validate: (v) => v.trim().length > 0 ? null : 'Nome obrigatório'
562
+ })
563
+
564
+ if (novoNome) await renameProject(novoNome)
565
+ ```
566
+
567
+ ---
568
+
569
+ ### Histórico de Notificações *(exclusivo)*
570
+
571
+ A VexUI mantém um registro interno de todos os alerts. Pode ser exibido como um painel de "sino de notificações".
572
+
573
+ ```js
574
+ // Acesso programático
575
+ const historico = vex.history.get()
576
+ // [{ id, type, title, message, timestamp, read }, ...]
577
+
578
+ vex.history.markAllRead()
579
+ vex.history.clear()
580
+
581
+ // Painel visual ancorado a um ícone
582
+ vex.history.open('#icone-notificacoes')
583
+ ```
584
+
585
+ ---
586
+
587
+ ### Controle global
588
+
589
+ ```js
590
+ // Remove tudo
591
+ vex.dismissAll()
592
+
593
+ // Com filtros
594
+ vex.dismissAll({ type: 'error' })
595
+ vex.dismissAll({ position: 'fixed' })
596
+
597
+ // Fecha um alert/modal específico pelo ID retornado
598
+ const id = vex.alert.loading('Processando...')
599
+ vex.dismiss(id)
600
+
601
+ // Configuração global padrão
602
+ vex.configure({
603
+ duration: 5000,
604
+ position: 'top',
605
+ maxStack: 3,
606
+ animate: 'slide',
607
+ })
608
+ ```
609
+
610
+ ---
611
+
612
+ ## Sistema de Temas
613
+
614
+ ### CSS Tokens (personalizável)
615
+
616
+ ```css
617
+ /* Cole no seu CSS e sobrescreva o que precisar */
618
+ :root {
619
+ /* Aparência geral */
620
+ --vex-radius: 14px;
621
+ --vex-blur: 20px;
622
+ --vex-shadow: 0 8px 32px rgba(0, 0, 0, 0.3);
623
+ --vex-border-width: 1px;
624
+ --vex-font: inherit;
625
+ --vex-progress-h: 3px;
626
+
627
+ /* Cores por tipo */
628
+ --vex-success-bg: rgba(5, 46, 22, 0.85);
629
+ --vex-success-border: rgba(34, 197, 94, 0.35);
630
+ --vex-success-text: #4ade80;
631
+ --vex-success-accent: #22c55e;
632
+
633
+ --vex-error-bg: rgba(40, 5, 5, 0.85);
634
+ --vex-error-border: rgba(239, 68, 68, 0.35);
635
+ --vex-error-text: #f87171;
636
+ --vex-error-accent: #ef4444;
637
+
638
+ /* ... warning, info, neutral ... */
639
+ }
640
+ ```
641
+
642
+ ### Temas prontos
643
+
644
+ ```js
645
+ // Importar no seu CSS/JS
646
+ import 'vexui/themes/glass' // Glassmorphism (padrão)
647
+ import 'vexui/themes/flat' // Flat design, sem blur
648
+ import 'vexui/themes/outline' // Apenas bordas
649
+ import 'vexui/themes/minimal' // Ultra-discreto
650
+ import 'vexui/themes/neon' // Neon / cyberpunk
651
+ import 'vexui/themes/pastel' // Tons suaves
652
+ ```
653
+
654
+ ### Alternar Dark / Light
655
+
656
+ ```js
657
+ vex.setTheme('dark') // força dark
658
+ vex.setTheme('light') // força light
659
+ vex.setTheme('auto') // respeita o sistema (padrão)
660
+ ```
661
+
662
+ ### Tema por instância
663
+
664
+ ```js
665
+ // Sobrescreve o visual apenas desta notificação
666
+ vex.alert.success('Deploy OK!', {
667
+ theme: {
668
+ background: 'rgba(5, 46, 22, 0.95)',
669
+ border: 'rgba(34, 197, 94, 0.6)',
670
+ progressColor: '#4ade80',
671
+ borderRadius: '20px',
672
+ }
673
+ })
674
+ ```
675
+
676
+ ---
677
+
678
+ ## Acessibilidade
679
+
680
+ Todos os componentes são construídos seguindo **WCAG 2.1 AA** e **WAI-ARIA 1.2**.
681
+
682
+ | Recurso | Implementação |
683
+ |---|---|
684
+ | `role="alert"` | Alerts anunciados imediatamente por screen readers |
685
+ | `role="dialog"` | Modals e Drawers com `aria-modal="true"` |
686
+ | `aria-live` | Região de alerts com `polite` ou `assertive` por prioridade |
687
+ | `aria-labelledby` | Título do modal vinculado corretamente |
688
+ | `aria-describedby` | Mensagem vinculada ao elemento correto |
689
+ | Focus trap | Foco preso dentro do modal; restaurado ao fechar |
690
+ | Navegação por teclado | `Tab` / `Shift+Tab` entre ações; `Enter` confirma; `Esc` cancela |
691
+ | Contraste | Mínimo de 4.5:1 em todos os temas (WCAG AA) |
692
+ | `prefers-reduced-motion` | Animações desativadas; transições simples de opacidade |
693
+
694
+ ---
695
+
696
+ ## Integrações
697
+
698
+ ### Vanilla JavaScript
699
+
700
+ ```js
701
+ import vex from 'vexui'
702
+ import 'vexui/dist/vexui.css'
703
+
704
+ vex.alert.success('Pronto!')
705
+ ```
706
+
707
+ ### React
708
+
709
+ ```jsx
710
+ import { useVex } from 'vexui/react'
711
+
712
+ function MeuComponente() {
713
+ const vex = useVex()
714
+
715
+ const handleDelete = async () => {
716
+ const ok = await vex.modal.confirm({
717
+ title: 'Excluir item?',
718
+ type: 'danger',
719
+ })
720
+ if (ok) deleteItem()
721
+ }
722
+
723
+ return <button onClick={handleDelete}>Excluir</button>
724
+ }
725
+ ```
726
+
727
+ ### Vue 3
728
+
729
+ ```js
730
+ // main.js
731
+ import VexUI from 'vexui/vue'
732
+ app.use(VexUI)
733
+ ```
734
+
735
+ ```vue
736
+ <script setup>
737
+ import { useVex } from 'vexui/vue'
738
+ const vex = useVex()
739
+
740
+ const confirmar = async () => {
741
+ const ok = await vex.modal.confirm({ title: 'Tem certeza?' })
742
+ if (ok) executar()
743
+ }
744
+ </script>
745
+ ```
746
+
747
+ ### CDN / Script tag
748
+
749
+ ```html
750
+ <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/vexui/dist/vexui.css">
751
+ <script src="https://cdn.jsdelivr.net/npm/vexui/dist/vexui.umd.js"></script>
752
+
753
+ <script>
754
+ VexUI.alert.success('Funciona em qualquer projeto!')
755
+ </script>
756
+ ```
757
+
758
+ ---
759
+
760
+ ## API Completa
761
+
762
+ ### `vex.alert.*`
763
+
764
+ | Método | Retorno | Descrição |
765
+ |---|---|---|
766
+ | `vex.alert.success(msg, opts?)` | `string` (id) | Alert de sucesso |
767
+ | `vex.alert.error(msg, opts?)` | `string` (id) | Alert de erro |
768
+ | `vex.alert.warning(msg, opts?)` | `string` (id) | Alert de aviso |
769
+ | `vex.alert.info(msg, opts?)` | `string` (id) | Alert informativo |
770
+ | `vex.alert.neutral(msg, opts?)` | `string` (id) | Alert neutro |
771
+ | `vex.alert.loading(msg, opts?)` | `string` (id) | Alert com spinner; atualizável via `vex.update(id)` |
772
+ | `vex.alert.upload(msg, opts?)` | `string` (id) | Alert com barra de progresso de upload |
773
+ | `vex.alert.inline(selector, opts)` | `string` (id) | Renderiza dentro de um container |
774
+ | `vex.alert.fixed(opts)` | `string` (id) | Renderiza fixo na viewport |
775
+ | `vex.alert.attach(selector, opts)` | `string` (id) | Ancora a um elemento do DOM |
776
+ | `vex.alert.show(opts)` | `string` (id) | Método base — aceita qualquer configuração |
777
+
778
+ ### `vex.modal.*`
779
+
780
+ | Método | Retorno | Descrição |
781
+ |---|---|---|
782
+ | `vex.modal.confirm(opts)` | `Promise<boolean>` | Sim ou não |
783
+ | `vex.modal.alert(opts)` | `Promise<void>` | Apenas fechar |
784
+ | `vex.modal.form(opts)` | `Promise<object \| null>` | Dados do formulário |
785
+ | `vex.modal.prompt(opts)` | `Promise<string \| null>` | Texto digitado |
786
+ | `vex.modal.preview(opts)` | `void` | Preview de imagem / mídia |
787
+ | `vex.modal.custom(opts)` | `{ close }` | Modal com HTML/DOM livre |
788
+
789
+ ### `vex.*` — Métodos globais
790
+
791
+ | Método | Descrição |
792
+ |---|---|
793
+ | `vex.flow(steps[])` | Step Flow (wizard) multi-etapa |
794
+ | `vex.drawer(opts)` | Abre painel lateral deslizante |
795
+ | `vex.prompt.inline(selector, opts)` | Input contextual inline no DOM |
796
+ | `vex.update(id, opts)` | Atualiza alert ativo em tempo real |
797
+ | `vex.progress(id, { loaded, total })` | Atualiza progresso de upload |
798
+ | `vex.dismiss(id)` | Fecha alert ou modal específico |
799
+ | `vex.dismissAll(filter?)` | Fecha tudo (com filtro opcional) |
800
+ | `vex.setTheme(theme)` | `'dark'` · `'light'` · `'auto'` |
801
+ | `vex.configure(opts)` | Configura opções padrão globais |
802
+ | `vex.history.get()` | Retorna histórico de notificações |
803
+ | `vex.history.clear()` | Limpa o histórico |
804
+ | `vex.history.markAllRead()` | Marca todas como lidas |
805
+ | `vex.history.open(anchor)` | Abre painel visual de histórico |
806
+
807
+ ---
808
+
809
+ ## Roadmap
810
+
811
+ | Versão | Nome | Entregas |
812
+ |---|---|---|
813
+ | **v1.0** | Core | Alerts (6 tipos) · Fixed & Inline · Modals (confirm, alert, form, prompt, preview, custom) · Glassmorphism · Progress bar · Queue · Dark/Light auto |
814
+ | **v1.1** | Adapters | React hook · Vue 3 plugin · CDN build · Svelte store |
815
+ | **v1.2** | Power Features | Step Flow · Drawer · Inline Prompt · Attached Alert · Upload progress · Histórico |
816
+ | **v2.0** | Enterprise | 6 temas prontos · Painel de notificações built-in · i18n · TypeScript types completo · Storybook oficial |
817
+
818
+ ---
819
+
820
+ ## Licença
821
+
822
+ MIT © VexUI
823
+
824
+ ---
825
+
826
+ <div align="center">
827
+
828
+ Feito com ❤️ — **[npm](https://npmjs.com/package/vexui)** · **[Documentação](https://vexui.dev)** · **[Changelog](./CHANGELOG.md)**
829
+
830
+ </div>