@xjur-ui/react 3.1.3 → 4.0.1

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 (49) hide show
  1. package/CHANGELOG.md +1467 -5
  2. package/dist/components/controls/pin-input/index.d.ts +5 -0
  3. package/dist/components/controls/pin-input/index.js +1 -0
  4. package/dist/components/controls/pin-input/pin-input-caption.d.ts +2 -0
  5. package/dist/components/controls/pin-input/pin-input-caption.js +1 -0
  6. package/dist/components/controls/pin-input/pin-input-control.d.ts +6 -0
  7. package/dist/components/controls/pin-input/pin-input-control.js +1 -0
  8. package/dist/components/controls/pin-input/pin-input-hidden.d.ts +4 -0
  9. package/dist/components/controls/pin-input/pin-input-hidden.js +1 -0
  10. package/dist/components/controls/pin-input/pin-input-root.d.ts +31 -0
  11. package/dist/components/controls/pin-input/pin-input-root.js +1 -0
  12. package/dist/components/controls/pin-input/pin-input-trigger.d.ts +2 -0
  13. package/dist/components/controls/pin-input/pin-input-trigger.js +1 -0
  14. package/dist/components/message/index.d.ts +5 -0
  15. package/dist/components/message/index.js +1 -0
  16. package/dist/components/message/message-action.d.ts +3 -0
  17. package/dist/components/message/message-action.js +1 -0
  18. package/dist/components/message/message-close.d.ts +4 -0
  19. package/dist/components/message/message-close.js +1 -0
  20. package/dist/components/message/message-icon.d.ts +1 -0
  21. package/dist/components/message/message-icon.js +1 -0
  22. package/dist/components/message/message-root.d.ts +15 -0
  23. package/dist/components/message/message-root.js +1 -0
  24. package/dist/components/message/message-text.d.ts +3 -0
  25. package/dist/components/message/message-text.js +1 -0
  26. package/dist/components/selection-bar/index.d.ts +5 -58
  27. package/dist/components/selection-bar/index.js +1 -1
  28. package/dist/components/selection-bar/selection-bar-action-group.d.ts +2 -0
  29. package/dist/components/selection-bar/selection-bar-action-group.js +1 -0
  30. package/dist/components/selection-bar/selection-bar-action.d.ts +3 -0
  31. package/dist/components/selection-bar/selection-bar-action.js +1 -0
  32. package/dist/components/selection-bar/selection-bar-close.d.ts +3 -0
  33. package/dist/components/selection-bar/selection-bar-close.js +1 -0
  34. package/dist/components/selection-bar/selection-bar-root.d.ts +12 -0
  35. package/dist/components/selection-bar/selection-bar-root.js +1 -0
  36. package/dist/components/selection-bar/selection-bar-title.d.ts +4 -0
  37. package/dist/components/selection-bar/selection-bar-title.js +1 -0
  38. package/dist/components/toast/index.d.ts +1 -24
  39. package/dist/components/toast/index.js +1 -1
  40. package/dist/components/toast/toast-component.d.ts +10 -0
  41. package/dist/components/toast/toast-component.js +1 -0
  42. package/dist/components/toast/toast.d.ts +25 -0
  43. package/dist/components/toast/toast.js +1 -0
  44. package/dist/components/toast/toast.types.d.ts +6 -0
  45. package/dist/components/toast/toast.types.js +0 -0
  46. package/dist/index.css +1 -1
  47. package/package.json +10 -8
  48. package/dist/components/controls/otp-input.d.ts +0 -9
  49. package/dist/components/controls/otp-input.js +0 -1
package/CHANGELOG.md CHANGED
@@ -1,16 +1,1478 @@
1
1
  # @xjur-ui/react
2
2
 
3
- ## 3.1.3
3
+ ## 4.0.1
4
4
 
5
5
  ### Patch Changes
6
6
 
7
- - Add some fixes
7
+ - 60f29b7: Correção de bugs no Input Pin e Message/Toast components
8
8
 
9
- ## 3.1.2
9
+ ## 4.0.0
10
10
 
11
- ### Patch Changes
11
+ ### Major Changes
12
+
13
+ - 07e5bf1: # Migração de OTPInput para PinInput + Novo Componente Message
14
+
15
+ Esta release inclui duas mudanças importantes:
16
+ 1. **BREAKING CHANGE**: Migração do componente OTPInput para PinInput com arquitetura composicional
17
+ 2. **NEW FEATURE**: Adição do componente Message para feedback e notificações
18
+
19
+ ***
20
+
21
+ ## 1. Migração de OTPInput para PinInput com arquitetura composicional
22
+
23
+ ## Breaking Changes
24
+
25
+ **BREAKING CHANGE**: O componente `OTPInput` foi completamente substituído pelo novo componente `PinInput` com arquitetura composicional moderna.
26
+
27
+ ### Migração Necessária
28
+
29
+ #### Antes (OTPInput - Depreciado)
30
+
31
+ ```tsx
32
+ import {
33
+ OTPInputRoot,
34
+ OTPInputTrigger,
35
+ OTPInputInput,
36
+ OTPInputCaption,
37
+ OTPInputHiddenInput
38
+ } from '@xjur-ui/react/otp-input'
39
+ ;<OTPInputRoot state="normal" length={4} initial="1234">
40
+ <OTPInputTrigger>
41
+ <OTPInputInput index={0} />
42
+ <OTPInputInput index={1} />
43
+ <OTPInputInput index={2} />
44
+ <OTPInputInput index={3} />
45
+ </OTPInputTrigger>
46
+ <OTPInputCaption>Digite o código</OTPInputCaption>
47
+ <OTPInputHiddenInput name="code" />
48
+ </OTPInputRoot>
49
+ ```
50
+
51
+ #### Depois (PinInput - Novo)
52
+
53
+ ```tsx
54
+ import {
55
+ PinInput,
56
+ PinInputControl,
57
+ PinInputTrigger,
58
+ PinInputCaption
59
+ } from '@xjur-ui/react/pin-input'
60
+ ;<PinInput state="normal" length={4} defaultValue="1234" name="code">
61
+ <PinInputTrigger>
62
+ <PinInputControl index={0} />
63
+ <PinInputControl index={1} />
64
+ <PinInputControl index={2} />
65
+ <PinInputControl index={3} />
66
+ </PinInputTrigger>
67
+ <PinInputCaption>Digite o código</PinInputCaption>
68
+ </PinInput>
69
+ ```
70
+
71
+ ### Principais Mudanças na API
72
+
73
+ | OTPInput (Antigo) | PinInput (Novo) | Notas |
74
+ | --------------------- | ---------------------------------------- | ------------------------------------------ |
75
+ | `OTPInputRoot` | `PinInput` | Renomeado para seguir padrão composicional |
76
+ | `OTPInputInput` | `PinInputControl` | Nome mais descritivo |
77
+ | `initial` prop | `defaultValue` prop | API mais consistente com React |
78
+ | `OTPInputHiddenInput` | Campo automático via prop `name` | Simplificado |
79
+ | Sem callbacks | `onChangeValue`, `onComplete`, `onError` | Maior controle |
80
+ | Sem auto-submit | `autoSubmit` prop | Nova funcionalidade |
81
+ | Sem placeholder | `placeholder` prop | Melhoria UX |
82
+
83
+ ## Novas Funcionalidades
84
+
85
+ ### 1. Auto-Submit de Formulários
86
+
87
+ ```tsx
88
+ <PinInput autoSubmit={true} name="code" onError={handleError}>
89
+ {/* Submete automaticamente quando completo */}
90
+ </PinInput>
91
+ ```
92
+
93
+ ### 2. Placeholder Posicional
94
+
95
+ ```tsx
96
+ <PinInput placeholder="0000">{/* Mostra "0" em cada campo vazio */}</PinInput>
97
+ ```
98
+
99
+ ### 3. Callbacks Detalhados
100
+
101
+ ```tsx
102
+ <PinInput
103
+ onChangeValue={(value) => console.log('Valor:', value)}
104
+ onComplete={(value) => console.log('Completo:', value)}
105
+ onError={(error) => console.error('Erro:', error)}
106
+ >
107
+ ```
108
+
109
+ ### 4. Hidden Input Automático
110
+
111
+ ```tsx
112
+ <PinInput name="verification_code">
113
+ {/* Cria automaticamente <input type="hidden" name="verification_code" /> */}
114
+ </PinInput>
115
+ ```
116
+
117
+ ### 5. Colagem Inteligente de Código
118
+ - Detecta quando usuário cola código completo
119
+ - Distribui automaticamente pelos campos
120
+ - Valida todos os caracteres contra padrão regex
121
+
122
+ ### 6. Validação Customizada por Campo
123
+
124
+ ```tsx
125
+ <PinInputControl pattern="[A-Z0-9]" inputMode="text" />
126
+ ```
127
+
128
+ ## Melhorias de Performance
129
+ - **Context memoizado**: Reduz re-renders desnecessários
130
+ - **Callbacks estáveis**: `useCallback` para `setCodeAt` e `registerInput`
131
+ - **Refs otimizadas**: Mantém referências sem causar re-renders
132
+ - **Validação lazy**: Regex compilado apenas quando necessário
133
+
134
+ ## Melhorias de Acessibilidade
135
+ - `autoComplete="one-time-code"`: Melhor experiência em dispositivos móveis
136
+ - `inputMode="numeric"`: Exibe teclado numérico automaticamente
137
+ - Navegação por teclado completa (setas, backspace, tab)
138
+ - Estados visuais claros (normal, error, disabled)
139
+ - Suporte completo a leitores de tela
140
+
141
+ ## Melhorias de DX (Developer Experience)
142
+ - **TypeScript completo**: Tipos exportados e documentados
143
+ - **Hook de contexto**: `usePinInputContext()` para componentes customizados
144
+ - **Documentação**: README.md detalhado com exemplos práticos
145
+ - **Stories**: 9 exemplos no Storybook cobrindo todos os casos de uso
146
+ - **Tratamento de erros**: Callback `onError` para debugging
147
+
148
+ ## Arquivos Criados
149
+ - `packages/react/src/components/controls/pin-input/pin-input-root.tsx`
150
+ - `packages/react/src/components/controls/pin-input/pin-input-control.tsx`
151
+ - `packages/react/src/components/controls/pin-input/pin-input-trigger.tsx`
152
+ - `packages/react/src/components/controls/pin-input/pin-input-caption.tsx`
153
+ - `packages/react/src/components/controls/pin-input/index.ts`
154
+ - `packages/react/src/components/controls/pin-input/README.md`
155
+
156
+ ## Arquivos Removidos
157
+ - `packages/react/src/components/controls/otp-input.tsx`
158
+ - `apps/docs/src/components/otp-input.stories.tsx`
159
+
160
+ ## Arquivos Criados/Atualizados (Documentação)
161
+ - `apps/docs/src/components/pin-input.stories.tsx` - 9 stories interativas:
162
+ - **Playground**: Exemplo básico com controles interativos
163
+ - **SixDigits**: OTP de 6 dígitos
164
+ - **Error**: Estado de erro com validação
165
+ - **Disabled**: Estado desabilitado
166
+ - **AutoSubmit**: Submissão automática de formulário
167
+ - **WithDefaultValue**: Valor inicial pré-preenchido
168
+ - **Alphanumeric**: Validação customizada alfanumérica
169
+ - **WithMonitoring**: Monitoramento em tempo real
170
+ - **TwoFactorAuth**: Fluxo completo de autenticação 2FA
171
+
172
+ ## Casos de Uso Suportados
173
+ 1. ✅ Verificação de Email/SMS (OTP de 6 dígitos)
174
+ 2. ✅ Autenticação de Dois Fatores (2FA)
175
+ 3. ✅ PIN de Segurança (4 dígitos)
176
+ 4. ✅ Código de Ativação (alfanumérico)
177
+ 5. ✅ Verificação de Pagamento
178
+ 6. ✅ Reset de Senha
179
+ 7. ✅ Confirmação de Transação
180
+
181
+ ## Guia de Migração Detalhado
182
+
183
+ ### Passo 1: Atualizar Imports
184
+
185
+ ```diff
186
+ - import { OTPInputRoot, OTPInputTrigger, OTPInputInput, OTPInputCaption } from '@xjur-ui/react/otp-input'
187
+ + import { PinInput, PinInputTrigger, PinInputControl, PinInputCaption } from '@xjur-ui/react/pin-input'
188
+ ```
189
+
190
+ ### Passo 2: Renomear Componentes
191
+
192
+ ```diff
193
+ - <OTPInputRoot state="normal" length={4} initial="1234">
194
+ + <PinInput state="normal" length={4} defaultValue="1234" name="code">
195
+ <OTPInputTrigger>
196
+ - <OTPInputInput index={0} />
197
+ + <PinInputControl index={0} />
198
+ </OTPInputTrigger>
199
+ - <OTPInputHiddenInput name="code" />
200
+ </PinInput>
201
+ ```
202
+
203
+ ### Passo 3: Adicionar Callbacks (Opcional)
204
+
205
+ ```tsx
206
+ <PinInput
207
+ onComplete={(code) => {
208
+ // Código completo digitado
209
+ verifyCode(code)
210
+ }}
211
+ onChangeValue={(value) => {
212
+ // Cada alteração
213
+ console.log('Valor:', value)
214
+ }}
215
+ >
216
+ ```
217
+
218
+ ### Passo 4: Habilitar Auto-Submit (Opcional)
219
+
220
+ ```tsx
221
+ <form onSubmit={handleSubmit}>
222
+ <PinInput autoSubmit={true} name="code">
223
+ {/* Submete automaticamente ao completar */}
224
+ </PinInput>
225
+ </form>
226
+ ```
227
+
228
+ ## Compatibilidade
229
+ - ✅ React 19.1.1+
230
+ - ✅ TypeScript 5.x
231
+ - ✅ Tailwind CSS 4.x
232
+ - ✅ Navegadores modernos (Chrome, Firefox, Safari, Edge)
233
+ - ✅ Dispositivos móveis (iOS Safari, Chrome Mobile)
234
+
235
+ ## Próximos Passos
236
+
237
+ Após esta atualização, recomendamos:
238
+ 1. **Testar fluxos de autenticação**: Verifique todos os fluxos que usavam OTPInput
239
+ 2. **Revisar validações**: Configure validações customizadas se necessário
240
+ 3. **Implementar auto-submit**: Aproveite a nova funcionalidade para melhor UX
241
+ 4. **Adicionar tratamento de erros**: Use o callback `onError` para debugging
242
+
243
+ ## Suporte
244
+
245
+ Para dúvidas ou problemas com a migração, consulte:
246
+ - 📖 README.md completo em `packages/react/src/components/controls/pin-input/README.md`
247
+ - 📚 9 exemplos interativos no Storybook
248
+ - 🔍 TypeScript types para autocomplete e documentação inline
249
+
250
+ ***
251
+
252
+ ## 2. Novo Componente Message
253
+
254
+ ### Visão Geral
255
+
256
+ O **Message** é um novo componente composicional para exibir mensagens e notificações contextuais aos usuários. Perfeito para feedbacks de ações, alertas, avisos e mensagens de sucesso.
257
+
258
+ ### Características Principais
259
+
260
+ #### Arquitetura Composicional
261
+ - **MessageRoot**: Container principal com controle de variante e modo de exibição
262
+ - **MessageIcon**: Ícone automático baseado na variante (success, neutral, warning, error)
263
+ - **MessageText**: Componente de texto com truncate automático
264
+ - **MessageClose**: Botão de fechamento que remove o elemento do DOM
265
+
266
+ #### Variantes Visuais
267
+
268
+ | Variante | Ícone | Cor | Uso |
269
+ | -------- | ------- | -------- | ----------------------------------- |
270
+ | success | check | Verde | Confirmações de ações bem-sucedidas |
271
+ | neutral | info | Cinza | Informações gerais |
272
+ | warning | warning | Amarelo | Avisos que requerem atenção |
273
+ | error | error | Vermelho | Erros e problemas críticos |
274
+
275
+ #### Modos de Apresentação
276
+
277
+ **Full-Width (Padrão)**
278
+ - Largura total do container
279
+ - Ícone visível à esquerda
280
+ - Borda colorida de 4px à esquerda
281
+ - Padding generoso
282
+ - Ideal para mensagens de sistema
283
+
284
+ **Inline (Compacto)**
285
+ - Largura ajustada ao conteúdo (w-fit)
286
+ - Sem ícone
287
+ - Sem borda lateral
288
+ - Padding compacto
289
+ - Ideal para mensagens próximas a campos
290
+
291
+ ### API do Componente
292
+
293
+ #### MessageRoot Props
294
+
295
+ ```tsx
296
+ interface MessageRootProps {
297
+ variant?: 'success' | 'neutral' | 'warning' | 'error' // Padrão: 'neutral'
298
+ inline?: boolean // Padrão: false
299
+ children: React.ReactNode
300
+ // + todas as props de HTMLDivElement
301
+ }
302
+ ```
303
+
304
+ #### MessageIcon
305
+ - Renderiza automaticamente o ícone apropriado
306
+ - Não é exibido quando `inline={true}`
307
+ - Sem props customizáveis
308
+
309
+ #### MessageText
310
+ - Wrapper do Typography com truncate automático
311
+ - Aceita todas as props do Typography
312
+ - Herda cor do contexto da mensagem
313
+
314
+ #### MessageClose
315
+ - Botão que remove a mensagem do DOM
316
+ - Renderiza ícone "close" por padrão
317
+ - Aceita children customizados
318
+ - Aceita todas as props de `<button>`
319
+
320
+ ### Exemplos de Uso
321
+
322
+ #### Mensagem de Sucesso
323
+
324
+ ```tsx
325
+ import {
326
+ MessageRoot,
327
+ MessageIcon,
328
+ MessageText,
329
+ MessageClose
330
+ } from '@xjur-ui/react/message'
331
+ ;<MessageRoot variant="success">
332
+ <MessageIcon />
333
+ <MessageText>Documento salvo com sucesso!</MessageText>
334
+ <MessageClose />
335
+ </MessageRoot>
336
+ ```
337
+
338
+ #### Mensagem de Erro em Formulário
339
+
340
+ ```tsx
341
+ <MessageRoot variant="error">
342
+ <MessageIcon />
343
+ <MessageText>Por favor, preencha todos os campos obrigatórios.</MessageText>
344
+ </MessageRoot>
345
+ ```
346
+
347
+ #### Aviso Importante
348
+
349
+ ```tsx
350
+ <MessageRoot variant="warning">
351
+ <MessageIcon />
352
+ <MessageText>Esta ação não pode ser desfeita.</MessageText>
353
+ </MessageRoot>
354
+ ```
355
+
356
+ #### Mensagem Inline
357
+
358
+ ```tsx
359
+ <MessageRoot variant="neutral" inline>
360
+ <MessageText>Informação adicional</MessageText>
361
+ </MessageRoot>
362
+ ```
363
+
364
+ ### Funcionalidades
365
+
366
+ #### 1. Animação de Entrada
367
+ - Fade-in suave (250ms) para não assustar usuários
368
+ - Classes: `animate-in fade-in-0 duration-250`
369
+
370
+ #### 2. Fechamento Inteligente
371
+ - Remove o elemento do DOM ao clicar no botão de fechar
372
+ - Utiliza `ref.current?.remove()` para limpeza completa
373
+ - Callback `onClose` disponível via contexto
374
+
375
+ #### 3. Context API
376
+
377
+ ```tsx
378
+ interface MessageRootContextValue {
379
+ variant: MessageRootVariant
380
+ inline: boolean
381
+ onClose?: () => void
382
+ }
383
+
384
+ // Hook para componentes customizados
385
+ const { variant, inline, onClose } = useMessageRootContext()
386
+ ```
387
+
388
+ #### 4. Mapeamento Automático de Ícones
389
+
390
+ ```tsx
391
+ const iconMap = new Map<MessageRootVariant, React.ReactNode>([
392
+ ['success', <Icon name="check" className="text-success-idle" />],
393
+ ['neutral', <Icon name="info" className="text-icon-neutral-3" />],
394
+ ['warning', <Icon name="warning" className="text-warning-idle" />],
395
+ ['error', <Icon name="error" className="text-danger-idle" />]
396
+ ])
397
+ ```
398
+
399
+ ### Acessibilidade
400
+ - ✅ Botão de fechamento com `type="button"` para evitar submissão acidental
401
+ - ✅ Estados visuais claros com cores contrastantes
402
+ - ✅ Animação suave de entrada
403
+ - ✅ Remoção do DOM ao fechar para limpar árvore de acessibilidade
404
+ - ✅ Texto com truncate para evitar quebras visuais
405
+ - ✅ Suporte completo a leitores de tela
406
+
407
+ ### Performance
408
+ - **Context memoizado**: Reduz re-renders desnecessários
409
+ - **Callback estável**: `handleClose` com `useCallback`
410
+ - **Ícones pré-compilados**: Map de ícones criado uma única vez
411
+ - **Composição modular**: Componentes pequenos e focados
412
+
413
+ ### Documentação no Storybook
414
+
415
+ 10 stories interativas demonstrando todos os casos de uso:
416
+ 1. **Playground**: Exemplo interativo com controles
417
+ 2. **Success**: Mensagem de sucesso
418
+ 3. **Neutral**: Mensagem neutra/informativa
419
+ 4. **Warning**: Mensagem de aviso
420
+ 5. **Error**: Mensagem de erro
421
+ 6. **InlineSuccess**: Versão compacta de sucesso
422
+ 7. **InlineError**: Versão compacta de erro
423
+ 8. **WithoutClose**: Mensagem persistente sem botão fechar
424
+ 9. **LongText**: Demonstração com texto longo
425
+ 10. **MultipleMessages**: Showcase de todas as variantes
426
+
427
+ ### Casos de Uso Suportados
428
+ 1. ✅ Feedback de ações (salvar, deletar, enviar)
429
+ 2. ✅ Validação de formulários
430
+ 3. ✅ Avisos importantes
431
+ 4. ✅ Mensagens de erro
432
+ 5. ✅ Notificações de sistema
433
+ 6. ✅ Confirmações de operações
434
+ 7. ✅ Informações contextuais inline
435
+ 8. ✅ Alertas temporários
436
+ 9. ✅ Status de operações assíncronas
437
+ 10. ✅ Mensagens de onboarding
438
+
439
+ ### Arquivos Criados
440
+ - `packages/react/src/components/message/index.ts`
441
+ - `packages/react/src/components/message/message-root.tsx`
442
+ - `packages/react/src/components/message/message-icon.tsx`
443
+ - `packages/react/src/components/message/message-text.tsx`
444
+ - `packages/react/src/components/message/message-close.tsx`
445
+ - `apps/docs/src/components/message.stories.tsx`
446
+
447
+ ### Integração com Design System
448
+
449
+ O componente Message utiliza:
450
+ - **Design tokens** do @xjur-ui/styles para cores e espaçamentos
451
+ - **Sistema de ícones** via componente Icon
452
+ - **Typography** para texto consistente
453
+ - **TailwindCSS 4.x** para estilização
454
+ - **Tailwind Variants** (tv) para variantes CSS
455
+
456
+ ### TypeScript
457
+
458
+ Tipagem completa exportada:
459
+
460
+ ```tsx
461
+ export type MessageRootVariant = 'success' | 'neutral' | 'warning' | 'error'
462
+
463
+ export interface MessageRootProps extends ComponentProps<'div'> {
464
+ variant?: MessageRootVariant
465
+ inline?: boolean
466
+ children: React.ReactNode
467
+ }
468
+
469
+ export function useMessageRootContext(): MessageRootContextValue
470
+ ```
471
+
472
+ ### Compatibilidade
473
+ - ✅ React 19.1.1+
474
+ - ✅ TypeScript 5.x
475
+ - ✅ Tailwind CSS 4.x
476
+ - ✅ Navegadores modernos (Chrome, Firefox, Safari, Edge)
477
+ - ✅ Dispositivos móveis (iOS Safari, Chrome Mobile)
478
+
479
+ ### Roadmap Futuro
480
+
481
+ Possíveis melhorias para próximas versões:
482
+ - Auto-dismiss com timeout configurável
483
+ - Posicionamento fixo (toast-style)
484
+ - Animações de saída customizáveis
485
+ - Suporte a ações customizadas (além de close)
486
+ - Progress bar para mensagens temporárias
487
+ - Queue de mensagens
488
+ - Suporte a rich content (links, imagens)
489
+
490
+ ***
491
+
492
+ ## 3. Novo Componente Toast (toast-v2)
493
+
494
+ ### Visão Geral
495
+
496
+ O **Toast** é um sistema completo de notificações temporárias não intrusivas, construído sobre a biblioteca Sonner e o componente Message. Oferece uma API imperativa simples e poderosa para exibir notificações toast com posicionamento, ações e callbacks.
497
+
498
+ ### Características Principais
499
+
500
+ #### Baseado em Sonner
501
+ - **Library moderna e performática**: Sonner é a biblioteca toast mais popular e otimizada do ecossistema React
502
+ - **Empilhamento inteligente**: Gerenciamento automático de múltiplos toasts
503
+ - **Animações suaves**: CSS transforms otimizadas
504
+ - **Mobile-friendly**: Suporte a swipe gestures
505
+ - **Acessibilidade integrada**: ARIA live regions automáticas
506
+
507
+ #### Integração com Message
508
+ - Reutiliza componente Message para consistência visual
509
+ - Usa MessageIcon, MessageText, MessageAction e MessageClose
510
+ - Design tokens compartilhados
511
+ - Mesmos padrões de acessibilidade
512
+
513
+ #### Arquitetura
514
+ - **ToastWrapper**: Provider global baseado no Toaster do Sonner
515
+ - **toast()**: Função imperativa para disparar toasts
516
+ - **ToastComponent**: Componente interno que renderiza usando Message
12
517
 
13
- - test
518
+ ### API do Componente
519
+
520
+ O objeto `toast` expõe 3 métodos principais:
521
+
522
+ #### 1. toast.dispatch(message, options)
523
+
524
+ Dispara um novo toast e retorna o ID do toast criado.
525
+
526
+ ```tsx
527
+ function toast.dispatch(message: string, options?: {
528
+ variant?: 'primary' | 'destructive'
529
+ dismissible?: boolean
530
+ action?: { label: string; onClick: () => void }
531
+ position?: 'top-right' | 'top-left' | 'bottom-right' | 'bottom-left'
532
+ inline?: boolean
533
+ duration?: number // ms, default: 3000
534
+ toasterId?: string
535
+ onAutoClose?: (toast) => void
536
+ onDismiss?: (toast) => void
537
+ }): string // Retorna o ID do toast
538
+ ```
539
+
540
+ #### 2. toast.dismiss(toastId)
541
+
542
+ Fecha um toast específico pelo ID.
543
+
544
+ ```tsx
545
+ function toast.dismiss(toastId: string): void
546
+ ```
547
+
548
+ **Exemplo**:
549
+
550
+ ```tsx
551
+ const toastId = toast.dispatch('Processando...')
552
+ // Mais tarde...
553
+ toast.dismiss(toastId)
554
+ ```
555
+
556
+ #### 3. toast.clear()
557
+
558
+ Fecha todos os toasts ativos.
559
+
560
+ ```tsx
561
+ function toast.clear(): void
562
+ ```
563
+
564
+ **Exemplo**:
565
+
566
+ ```tsx
567
+ // Fechar todos os toasts ao navegar para outra página
568
+ toast.clear()
569
+ ```
570
+
571
+ #### Opções Disponíveis
572
+
573
+ | Opção | Tipo | Padrão | Descrição |
574
+ | ----------- | ---------------------------------------- | -------------- | --------------------------------------------- | ----------------------------------------- | --------------- |
575
+ | variant | `'primary' | 'destructive'` | `'primary'` | Estilo visual (mapeia para success/error) |
576
+ | dismissible | `boolean` | `true` | Se pode ser fechado manualmente |
577
+ | action | `{ label: string; onClick: () => void }` | `undefined` | Botão de ação adicional |
578
+ | position | `'top-right' | 'top-left' | ...` | `undefined` | Posição na tela |
579
+ | inline | `boolean` | `false` | Modo compacto |
580
+ | duration | `number` | `3000` | Duração em ms (Infinity se dismissible=false) |
581
+ | toasterId | `string` | `undefined` | ID do toaster específico |
582
+ | onAutoClose | `(toast) => void` | `undefined` | Callback ao fechar automaticamente |
583
+ | onDismiss | `(toast) => void` | `undefined` | Callback ao fechar |
584
+
585
+ ### Variantes
586
+
587
+ | Variante | Mapeia para Message | Visual | Uso |
588
+ | ----------- | ------------------- | ------------------------ | -------------------------------- |
589
+ | primary | success | Verde com ícone check | Confirmações e sucessos (padrão) |
590
+ | destructive | error | Vermelho com ícone error | Erros e ações destrutivas |
591
+
592
+ **Nota**: Para variantes `neutral` e `warning`, use o componente Message diretamente com posicionamento fixo.
593
+
594
+ ### Posições Disponíveis
595
+ - **top-right**: Canto superior direito
596
+ - **top-left**: Canto superior esquerdo
597
+ - **bottom-right**: Canto inferior direito (padrão Sonner)
598
+ - **bottom-left**: Canto inferior esquerdo
599
+
600
+ ### Exemplos de Uso
601
+
602
+ #### Setup Inicial
603
+
604
+ ```tsx
605
+ import { ToastWrapper } from '@xjur-ui/react/toast-v2'
606
+
607
+ function App() {
608
+ return (
609
+ <>
610
+ <ToastWrapper />
611
+ {/* Resto da aplicação */}
612
+ </>
613
+ )
614
+ }
615
+ ```
616
+
617
+ #### Toast Simples
618
+
619
+ ```tsx
620
+ import { toast } from '@xjur-ui/react/toast'
621
+
622
+ // Sucesso
623
+ toast.dispatch('Documento salvo com sucesso!')
624
+
625
+ // Erro
626
+ toast.dispatch('Erro ao processar solicitação', {
627
+ variant: 'destructive'
628
+ })
629
+ ```
630
+
631
+ #### Toast com Ação
632
+
633
+ ```tsx
634
+ toast.dispatch('Email enviado com sucesso', {
635
+ action: {
636
+ label: 'Desfazer',
637
+ onClick: () => undoSendEmail()
638
+ }
639
+ })
640
+ ```
641
+
642
+ #### Toast Persistente com Dismiss
643
+
644
+ ```tsx
645
+ const toastId = toast.dispatch('Processando... Por favor aguarde', {
646
+ dismissible: false,
647
+ duration: Infinity
648
+ })
649
+
650
+ // Depois de completar a tarefa
651
+ setTimeout(() => {
652
+ toast.dismiss(toastId)
653
+ toast.dispatch('Concluído!', { variant: 'primary' })
654
+ }, 3000)
655
+ ```
656
+
657
+ #### Fechar Todos os Toasts
658
+
659
+ ```tsx
660
+ // Disparar múltiplos toasts
661
+ toast.dispatch('Primeira notificação')
662
+ toast.dispatch('Segunda notificação')
663
+ toast.dispatch('Terceira notificação')
664
+
665
+ // Fechar todos de uma vez
666
+ toast.clear()
667
+ ```
668
+
669
+ #### Toast com Posição e Duração
670
+
671
+ ```tsx
672
+ toast.dispatch('Notificação importante', {
673
+ position: 'top-right',
674
+ duration: 5000 // 5 segundos
675
+ })
676
+ ```
677
+
678
+ #### Toast com Callbacks
679
+
680
+ ```tsx
681
+ toast.dispatch('Upload iniciado', {
682
+ onAutoClose: t => {
683
+ console.log('Toast auto-fechado:', t)
684
+ logAnalytics('toast_auto_close')
685
+ },
686
+ onDismiss: t => {
687
+ console.log('Toast fechado:', t)
688
+ }
689
+ })
690
+ ```
691
+
692
+ ### Funcionalidades
693
+
694
+ #### 1. Empilhamento Automático
695
+ - Sonner gerencia automaticamente a queue de toasts
696
+ - Toasts são empilhados verticalmente
697
+ - Animações coordenadas ao adicionar/remover
698
+
699
+ #### 2. Swipe to Dismiss (Mobile)
700
+ - Gestos de swipe para fechar em mobile
701
+ - Feedback visual durante o swipe
702
+ - Configuração automática pelo Sonner
703
+
704
+ #### 3. Auto-dismiss Inteligente
705
+ - Duração padrão de 3 segundos
706
+ - Ajuste automático para Infinity se `dismissible=false`
707
+ - Pause no hover (comportamento Sonner)
708
+
709
+ #### 4. Callbacks de Lifecycle
710
+ - `onAutoClose`: Chamado quando fecha automaticamente
711
+ - `onDismiss`: Chamado em qualquer tipo de fechamento
712
+ - Recebe objeto toast com ID e metadata
713
+
714
+ #### 5. Múltiplos Toasters
715
+ - Suporte a múltiplos toasters com IDs diferentes
716
+ - Útil para diferentes áreas da aplicação
717
+ - Configuração via `toasterId`
718
+
719
+ #### 6. Gerenciamento de Ciclo de Vida
720
+ - **Disparar**: `toast.dispatch()` retorna o ID do toast
721
+ - **Fechar específico**: `toast.dismiss(id)` fecha um toast pelo ID
722
+ - **Fechar todos**: `toast.clear()` limpa todos os toasts ativos
723
+ - Permite padrões avançados:
724
+ - Substituir toast de loading por sucesso
725
+ - Limpar notificações ao mudar de página
726
+ - Gerenciar toasts relacionados
727
+
728
+ ### Integração com Message
729
+
730
+ O Toast reutiliza completamente o componente Message:
731
+
732
+ ```tsx
733
+ // toast-component.tsx
734
+ export function ToastComponent({
735
+ variant = 'primary',
736
+ inline = false,
737
+ dismissible = true,
738
+ message,
739
+ action,
740
+ onDismiss
741
+ }: ToastComponentProps) {
742
+ return (
743
+ <MessageRoot inline={inline} variant={variant}>
744
+ <MessageIcon />
745
+ <MessageText>{message}</MessageText>
746
+
747
+ {action && (
748
+ <MessageAction variant={variant} onClick={action.onClick}>
749
+ {action.label}
750
+ </MessageAction>
751
+ )}
752
+
753
+ {dismissible && <MessageClose onClick={onDismiss} />}
754
+ </MessageRoot>
755
+ )
756
+ }
757
+ ```
758
+
759
+ Isso garante:
760
+ - ✅ Consistência visual total
761
+ - ✅ Mesmos design tokens
762
+ - ✅ Manutenção centralizada
763
+ - ✅ Reutilização de código
764
+
765
+ ### Acessibilidade
766
+ - ✅ **ARIA live regions**: Sonner cria automaticamente
767
+ - ✅ **Screen readers**: Anúncios automáticos de toasts
768
+ - ✅ **Navegação por teclado**: Tab, Enter, Escape
769
+ - ✅ **Focus management**: Foco adequado em ações
770
+ - ✅ **Swipe gestures**: Mobile acessível
771
+ - ✅ **Prefers-reduced-motion**: Respeita preferências do usuário
772
+ - ✅ **Labels apropriadas**: Botões com texto claro
773
+
774
+ ### Performance
775
+ - ✅ **Renderização otimizada**: Sonner usa virtualização
776
+ - ✅ **Animações com transforms**: GPU-accelerated
777
+ - ✅ **Limpeza automática**: Remove toasts do DOM após fechar
778
+ - ✅ **Memoização**: Context e callbacks memoizados
779
+ - ✅ **Bundle size pequeno**: ~10KB (Sonner) + componentes existentes
780
+
781
+ ### Documentação no Storybook
782
+
783
+ 13 stories interativas cobrindo todos os casos:
784
+ 1. **Playground**: Exemplo básico interativo
785
+ 2. **Primary**: Toast de sucesso
786
+ 3. **Destructive**: Toast de erro
787
+ 4. **WithAction**: Toast com botão de ação
788
+ 5. **NotDismissible**: Toast persistente
789
+ 6. **CustomDuration**: Durações customizadas (1s, 10s)
790
+ 7. **Positions**: Todas as 4 posições
791
+ 8. **InlineMode**: Modo compacto
792
+ 9. **WithCallbacks**: Demonstração de callbacks
793
+ 10. **MultipleToasts**: Empilhamento de 3 toasts
794
+ 11. **DismissSpecific**: Fechar toast específico por ID
795
+ 12. **ClearAll**: Fechar todos os toasts ativos
796
+ 13. **RealWorldExample**: Exemplos CRUD práticos
797
+
798
+ ### Casos de Uso Suportados
799
+ 1. ✅ Confirmações de ações (salvar, deletar, enviar)
800
+ 2. ✅ Notificações de erro
801
+ 3. ✅ Ações com desfazer (undo)
802
+ 4. ✅ Status de upload/download
803
+ 5. ✅ Notificações de sistema
804
+ 6. ✅ Feedback de formulários
805
+ 7. ✅ Operações assíncronas
806
+ 8. ✅ Alertas temporários
807
+ 9. ✅ Confirmações destrutivas
808
+ 10. ✅ Múltiplas notificações simultâneas
809
+
810
+ ### Arquivos Criados/Substituídos
811
+
812
+ **Toast (substituição completa)**:
813
+ - `packages/react/src/components/toast/index.ts`
814
+ - `packages/react/src/components/toast/toast.tsx`
815
+ - `packages/react/src/components/toast/toast-component.tsx`
816
+ - `packages/react/src/components/toast/toast.types.ts`
817
+
818
+ **Message**:
819
+ - `packages/react/src/components/message/message-action.tsx` (novo)
820
+
821
+ **Documentação**:
822
+ - `apps/docs/src/components/toast.stories.tsx` (reescrito completamente)
823
+
824
+ **Observação**: O componente Toast foi completamente reescrito. O código antigo baseado em Radix foi substituído por uma nova implementação baseada em Sonner.
825
+
826
+ ### Dependências
827
+
828
+ Nova dependência adicionada:
829
+
830
+ ```json
831
+ {
832
+ "dependencies": {
833
+ "sonner": "^1.x"
834
+ }
835
+ }
836
+ ```
837
+
838
+ **Sonner**: Library toast moderna, leve e performática
839
+ - Bundle: ~10KB gzipped
840
+ - Zero dependencies além de React
841
+ - Amplamente adotada pela comunidade
842
+ - Manutenção ativa
843
+
844
+ ### Comparação: Toast vs Message
845
+
846
+ | Aspecto | Toast (toast-v2) | Message |
847
+ | ---------------- | ------------------------- | ------------------------- |
848
+ | **Posição** | Fixo na tela (flutuante) | Inline no layout |
849
+ | **Duração** | Temporário (auto-dismiss) | Persistente |
850
+ | **API** | Imperativa (`toast()`) | Declarativa (JSX) |
851
+ | **Uso** | Notificações globais | Feedback contextual |
852
+ | **Empilhamento** | Automático (Sonner queue) | Manual |
853
+ | **Biblioteca** | Sonner + Message | Nativo |
854
+ | **Callbacks** | onAutoClose, onDismiss | onClose via ref |
855
+ | **Posições** | 4 cantos da tela | Onde for renderizado |
856
+ | **Ações** | Suporte via MessageAction | Suporte via MessageAction |
857
+
858
+ ### Boas Práticas
859
+ 1. **Use Toast para feedback não crítico**: Confirmações rápidas, updates de status
860
+ 2. **Use Message para feedback crítico inline**: Erros de formulário, avisos importantes
861
+ 3. **Limite a duração**: 3-5s para leitura confortável
862
+ 4. **Evite spam de toasts**: Não dispare múltiplos toasts em sequência rápida
863
+ 5. **Forneça ações quando relevante**: "Desfazer", "Ver detalhes"
864
+ 6. **Posicione adequadamente**: top-right para notificações, bottom-right para status
865
+ 7. **Teste em mobile**: Verifique swipe gestures
866
+ 8. **Use callbacks para analytics**: Track abertura e fechamento
867
+ 9. **Gerencie o ciclo de vida**: Use `dismiss()` para substituir loading por sucesso
868
+ 10. **Limpe ao navegar**: Use `clear()` ao mudar de página/contexto
869
+ 11. **Armazene IDs quando necessário**: Salve o retorno de `dispatch()` para controle posterior
870
+
871
+ ### Migração do Toast Antigo (Radix)
872
+
873
+ O toast antigo baseado em Radix UI será removido. Migração:
874
+
875
+ #### Antes (Toast Radix - Depreciado)
876
+
877
+ ```tsx
878
+ import {
879
+ ToastProvider,
880
+ ToastComponent,
881
+ ToastViewport
882
+ } from '@xjur-ui/react/toast'
883
+ ;<ToastProvider>
884
+ <ToastComponent variant="success" description="Salvo!" />
885
+ <ToastViewport />
886
+ </ToastProvider>
887
+ ```
888
+
889
+ #### Depois (Toast Sonner - Novo)
890
+
891
+ ```tsx
892
+ import { ToastWrapper, toast } from '@xjur-ui/react/toast'
893
+
894
+ // No root da app
895
+ ;<ToastWrapper />
896
+
897
+ // Onde precisar
898
+ toast.dispatch('Salvo!', { variant: 'primary' })
899
+
900
+ // Com controle de ciclo de vida
901
+ const toastId = toast.dispatch('Processando...')
902
+ toast.dismiss(toastId) // Fechar específico
903
+ toast.clear() // Fechar todos
904
+ ```
905
+
906
+ ### Compatibilidade
907
+ - ✅ React 19.1.1+
908
+ - ✅ TypeScript 5.x
909
+ - ✅ Tailwind CSS 4.x
910
+ - ✅ Navegadores modernos (Chrome, Firefox, Safari, Edge)
911
+ - ✅ iOS Safari 12+
912
+ - ✅ Chrome Mobile
913
+ - ✅ Suporte SSR/SSG
914
+
915
+ ### Roadmap Futuro
916
+
917
+ Melhorias planejadas:
918
+ - Mais variantes (neutral, warning) mapeando para Message
919
+ - Suporte a rich content (imagens, progress bars)
920
+ - Posições customizadas (não apenas cantos)
921
+ - Temas customizados
922
+ - Agrupamento de toasts relacionados
923
+ - Priorização de toasts
924
+ - Rate limiting automático
925
+
926
+ ***
927
+
928
+ ## 4. Novo Componente SelectionBar (selection-bar-v2)
929
+
930
+ ### Visão Geral
931
+
932
+ O **SelectionBar** é um componente composicional que exibe uma barra de ações flutuante na parte inferior da tela quando itens são selecionados. Renderizado via Portal React, é ideal para operações em lote em listas, tabelas e grids, oferecendo uma experiência moderna e intuitiva.
933
+
934
+ ### Características Principais
935
+
936
+ #### Arquitetura Composicional Moderna
937
+ - **SelectionBarRoot**: Container principal com gerenciamento de estado e portal
938
+ - **SelectionBarTitleRoot**: Container para título e botão de fechar
939
+ - **SelectionBarTitle**: Texto do título (wrapper do Typography)
940
+ - **SelectionBarClose**: Botão para fechar a barra
941
+ - **SelectionBarActionGroup**: Container de ações com suporte a overflow
942
+ - **SelectionBarAction**: Botão de ação (wrapper do Button)
943
+
944
+ #### Portal e Posicionamento Fixo
945
+ - Renderizado via `createPortal` React
946
+ - Alvo: elemento `#selection-bar-root` ou `document.body`
947
+ - Posição: `fixed bottom-[60px]` (acima de barras de navegação)
948
+ - Centralizado horizontalmente: `left-1/2 -translate-x-1/2`
949
+ - Z-index: 1000 (acima de outros elementos)
950
+
951
+ #### Animações e Transições
952
+ - **Entrada**: `slide-in-from-top` (200ms)
953
+ - **Saída**: `slide-out-to-bottom` (200ms)
954
+ - Auto-remoção do DOM após fechamento
955
+ - Estados visuais: `data-state="open|closed"`
956
+
957
+ ### API do Componente
958
+
959
+ #### SelectionBarRoot
960
+
961
+ ```tsx
962
+ interface SelectionBarRootProps {
963
+ open?: boolean // Padrão: true
964
+ onOpenChange?: (open: boolean) => void
965
+ className?: string
966
+ children: React.ReactNode
967
+ // + todas as props de HTMLDivElement
968
+ }
969
+ ```
970
+
971
+ **Context API**:
972
+
973
+ ```tsx
974
+ interface SelectionBarContextValue {
975
+ open: boolean
976
+ onClose: () => void
977
+ }
978
+
979
+ // Hook
980
+ const { open, onClose } = useSelectionBarContext()
981
+ ```
982
+
983
+ #### Outros Componentes
984
+
985
+ | Componente | Base | Props Especiais |
986
+ | ----------------------- | ---------- | ----------------------------- |
987
+ | SelectionBarTitleRoot | div | Container flexbox |
988
+ | SelectionBarTitle | Typography | weight="medium", cor neutra |
989
+ | SelectionBarClose | Button | size="icon_md", ícone close |
990
+ | SelectionBarActionGroup | div | Flexbox com overflow-x-hidden |
991
+ | SelectionBarAction | Button | className="shrink-0" |
992
+
993
+ ### Exemplos de Uso
994
+
995
+ #### Seleção Básica em Tabela
996
+
997
+ ```tsx
998
+ import {
999
+ SelectionBarRoot,
1000
+ SelectionBarTitleRoot,
1001
+ SelectionBarTitle,
1002
+ SelectionBarClose,
1003
+ SelectionBarActionGroup,
1004
+ SelectionBarAction
1005
+ } from '@xjur-ui/react/selection-bar'
1006
+ import { Icon } from '@xjur-ui/react/icon'
1007
+
1008
+ const [selectedIds, setSelectedIds] = useState<string[]>([])
1009
+
1010
+ {
1011
+ selectedIds.length > 0 && (
1012
+ <SelectionBarRoot>
1013
+ <SelectionBarTitleRoot>
1014
+ <SelectionBarClose />
1015
+ <SelectionBarTitle>
1016
+ {selectedIds.length} selecionados
1017
+ </SelectionBarTitle>
1018
+ </SelectionBarTitleRoot>
1019
+
1020
+ <SelectionBarActionGroup>
1021
+ <SelectionBarAction onClick={handleExport}>
1022
+ <Icon name="download" />
1023
+ Exportar
1024
+ </SelectionBarAction>
1025
+ <SelectionBarAction onClick={handleArchive}>
1026
+ Arquivar
1027
+ </SelectionBarAction>
1028
+ <SelectionBarAction variant="destructive" onClick={handleDelete}>
1029
+ <Icon name="delete" />
1030
+ Excluir
1031
+ </SelectionBarAction>
1032
+ </SelectionBarActionGroup>
1033
+ </SelectionBarRoot>
1034
+ )
1035
+ }
1036
+ ```
1037
+
1038
+ #### Com Controle de Estado
1039
+
1040
+ ```tsx
1041
+ const [open, setOpen] = useState(false)
1042
+ const [selectedItems, setSelectedItems] = useState([])
1043
+
1044
+ <SelectionBarRoot
1045
+ open={open}
1046
+ onOpenChange={(newOpen) => {
1047
+ setOpen(newOpen)
1048
+ if (!newOpen) {
1049
+ // Limpar seleções ao fechar
1050
+ setSelectedItems([])
1051
+ }
1052
+ }}
1053
+ >
1054
+ <SelectionBarTitleRoot>
1055
+ <SelectionBarClose />
1056
+ <SelectionBarTitle>
1057
+ {selectedItems.length} selecionados
1058
+ </SelectionBarTitle>
1059
+ </SelectionBarTitleRoot>
1060
+
1061
+ <SelectionBarActionGroup>
1062
+ <SelectionBarAction>Exportar PDF</SelectionBarAction>
1063
+ <SelectionBarAction>Compartilhar</SelectionBarAction>
1064
+ <SelectionBarAction variant="destructive">
1065
+ <Icon name="delete" />
1066
+ </SelectionBarAction>
1067
+ </SelectionBarActionGroup>
1068
+ </SelectionBarRoot>
1069
+ ```
1070
+
1071
+ #### Operações em Lote
1072
+
1073
+ ```tsx
1074
+ <SelectionBarRoot>
1075
+ <SelectionBarTitleRoot>
1076
+ <SelectionBarClose />
1077
+ <SelectionBarTitle>5 documentos selecionados</SelectionBarTitle>
1078
+ </SelectionBarTitleRoot>
1079
+
1080
+ <SelectionBarActionGroup>
1081
+ <SelectionBarAction>Exportar PDF</SelectionBarAction>
1082
+ <SelectionBarAction>Exportar Excel</SelectionBarAction>
1083
+ <SelectionBarAction>Compartilhar</SelectionBarAction>
1084
+ <SelectionBarAction>Mover para</SelectionBarAction>
1085
+ <SelectionBarAction>Arquivar</SelectionBarAction>
1086
+
1087
+ <SelectionBarAction size="icon_md" variant="destructive">
1088
+ <Icon name="delete" />
1089
+ </SelectionBarAction>
1090
+ </SelectionBarActionGroup>
1091
+ </SelectionBarRoot>
1092
+ ```
1093
+
1094
+ ### Funcionalidades
1095
+
1096
+ #### 1. Portal Rendering
1097
+ - Renderiza fora da hierarquia DOM do componente pai
1098
+ - Evita problemas de z-index e overflow
1099
+ - Permite posicionamento fixo global
1100
+ - Fallback automático para `document.body`
1101
+
1102
+ #### 2. Gerenciamento de Estado
1103
+ - Estado controlado via props `open` e `onOpenChange`
1104
+ - Estado interno quando não controlado
1105
+ - Callback ao fechar para sincronizar com estado externo
1106
+ - Auto-remoção do DOM após animação de saída
1107
+
1108
+ #### 3. Overflow Horizontal
1109
+ - Container de ações com `overflow-x-hidden`
1110
+ - Scroll horizontal automático em mobile
1111
+ - Ações com `shrink-0` para não comprimir
1112
+ - Suporta muitas ações sem quebrar layout
1113
+
1114
+ #### 4. Context API
1115
+ - Hook `useSelectionBarContext()` para componentes customizados
1116
+ - Acesso a `open` e `onClose` em qualquer nível
1117
+ - Permite criar componentes especializados
1118
+
1119
+ #### 5. Integração com Componentes Base
1120
+ - Usa Button para ações (todas as variantes disponíveis)
1121
+ - Usa Typography para título (todas as props disponíveis)
1122
+ - Usa Icon para ícones
1123
+ - Mantém consistência visual com design system
1124
+
1125
+ ### Acessibilidade
1126
+ - ✅ **Navegação por teclado**: Todos os botões são focáveis
1127
+ - ✅ **Ícones descritivos**: Ações com ícones e/ou texto claro
1128
+ - ✅ **Botão de fechar**: Sempre visível e acessível
1129
+ - ✅ **Contraste adequado**: Fundo primário com texto legível
1130
+ - ✅ **Animações**: Respeitam `prefers-reduced-motion`
1131
+ - ✅ **Focus management**: Foco adequado em botões
1132
+
1133
+ ### Performance
1134
+ - ✅ **Portal rendering**: Otimizado pelo React
1135
+ - ✅ **Animações CSS**: GPU-accelerated com transforms
1136
+ - ✅ **Auto-remoção**: Limpa DOM após fechamento
1137
+ - ✅ **Context memoizado**: Evita re-renders desnecessários
1138
+ - ✅ **Callbacks estáveis**: `useCallback` para `handleClose`
1139
+ - ✅ **Composição modular**: Componentes pequenos e focados
1140
+
1141
+ ### Documentação no Storybook
1142
+
1143
+ 8 stories interativas cobrindo todos os casos:
1144
+ 1. **Playground**: Exemplo básico com 3 itens selecionados
1145
+ 2. **WithManyActions**: Múltiplas ações com overflow
1146
+ 3. **WithIconsOnly**: Apenas ícones (compacto)
1147
+ 4. **WithMixedActions**: Mistura de ícones e texto
1148
+ 5. **ControlledState**: Controle total do estado
1149
+ 6. **TableIntegration**: Integração completa com tabela
1150
+ 7. **MinimalActions**: Uma única ação
1151
+ 8. **WithVariants**: Diferentes variantes de botão
1152
+
1153
+ ### Casos de Uso Suportados
1154
+ 1. ✅ Seleção em tabelas
1155
+ 2. ✅ Operações em lote em listas
1156
+ 3. ✅ Seleção múltipla em grids
1157
+ 4. ✅ Ações de arquivamento em massa
1158
+ 5. ✅ Exportação de múltiplos itens
1159
+ 6. ✅ Compartilhamento em lote
1160
+ 7. ✅ Exclusão de múltiplos registros
1161
+ 8. ✅ Movimentação de arquivos
1162
+ 9. ✅ Marcação de leitura/não lido
1163
+ 10. ✅ Aprovação/rejeição em lote
1164
+
1165
+ ### Arquivos Criados/Substituídos
1166
+
1167
+ **SelectionBar (substituição completa)**:
1168
+ - `packages/react/src/components/selection-bar/index.ts`
1169
+ - `packages/react/src/components/selection-bar/selection-bar-root.tsx`
1170
+ - `packages/react/src/components/selection-bar/selection-bar-title.tsx`
1171
+ - `packages/react/src/components/selection-bar/selection-bar-close.tsx`
1172
+ - `packages/react/src/components/selection-bar/selection-bar-action.tsx`
1173
+ - `packages/react/src/components/selection-bar/selection-bar-action-group.tsx`
1174
+
1175
+ **Documentação**:
1176
+ - `apps/docs/src/components/selection-bar.stories.tsx` (reescrito completamente)
1177
+
1178
+ **Observação**: O componente SelectionBar foi completamente reescrito. O código antigo foi substituído por uma nova implementação composicional com portal, estado gerenciado e animações.
1179
+
1180
+ ### Comparação: Versão Antiga vs Nova
1181
+
1182
+ | Aspecto | Antiga | Nova (v2) |
1183
+ | ---------------- | ----------------------- | ---------------------------- |
1184
+ | **Arquitetura** | Monolítica | Composicional |
1185
+ | **Renderização** | Normal no DOM | Portal (flutuante) |
1186
+ | **Estado** | Não gerenciado | Controlado/não-controlado |
1187
+ | **Animações** | Básicas ou inexistentes | Slide-in/out suaves |
1188
+ | **Overflow** | Sem tratamento | Scroll horizontal automático |
1189
+ | **Fechamento** | Manual | Auto-remoção do DOM |
1190
+ | **Context** | Sem context | Context API completa |
1191
+ | **Callbacks** | Limitados | `onOpenChange` completo |
1192
+ | **Composição** | 1-2 componentes | 6 componentes especializados |
1193
+
1194
+ ### Boas Práticas
1195
+ 1. **Use para operações em lote**: Perfeito para ações em múltiplos itens
1196
+ 2. **Limite o número de ações**: 3-5 ações principais
1197
+ 3. **Priorize ações importantes**: Mais usadas primeiro
1198
+ 4. **Indique quantidade selecionada**: Sempre mostre o número
1199
+ 5. **Forneça feedback visual**: Ícones e cores apropriadas
1200
+ 6. **Feche ao limpar seleção**: Use `onOpenChange` para sincronizar
1201
+ 7. **Teste em mobile**: Verifique overflow horizontal
1202
+ 8. **Confirme ações destrutivas**: Use diálogos para deletar
1203
+ 9. **Crie portal root**: Adicione `<div id="selection-bar-root" />` no app
1204
+ 10. **Sincronize estado**: Mantenha seleções e barra em sync
1205
+
1206
+ ### Migração da Versão Antiga
1207
+
1208
+ #### Antes (SelectionBar Antigo - Depreciado)
1209
+
1210
+ ```tsx
1211
+ import { SelectionBar } from '@xjur-ui/react/selection-bar'
1212
+ ;<SelectionBar
1213
+ title="3 selecionados"
1214
+ actions={[
1215
+ { label: 'Exportar', onClick: handleExport },
1216
+ { label: 'Excluir', onClick: handleDelete }
1217
+ ]}
1218
+ />
1219
+ ```
1220
+
1221
+ #### Depois (SelectionBar Novo - Composicional)
1222
+
1223
+ ```tsx
1224
+ import {
1225
+ SelectionBarRoot,
1226
+ SelectionBarTitleRoot,
1227
+ SelectionBarTitle,
1228
+ SelectionBarClose,
1229
+ SelectionBarActionGroup,
1230
+ SelectionBarAction
1231
+ } from '@xjur-ui/react/selection-bar'
1232
+ ;<SelectionBarRoot>
1233
+ <SelectionBarTitleRoot>
1234
+ <SelectionBarClose />
1235
+ <SelectionBarTitle>3 selecionados</SelectionBarTitle>
1236
+ </SelectionBarTitleRoot>
1237
+
1238
+ <SelectionBarActionGroup>
1239
+ <SelectionBarAction onClick={handleExport}>Exportar</SelectionBarAction>
1240
+ <SelectionBarAction variant="destructive" onClick={handleDelete}>
1241
+ Excluir
1242
+ </SelectionBarAction>
1243
+ </SelectionBarActionGroup>
1244
+ </SelectionBarRoot>
1245
+ ```
1246
+
1247
+ ### Compatibilidade
1248
+ - ✅ React 19.1.1+
1249
+ - ✅ TypeScript 5.x
1250
+ - ✅ Tailwind CSS 4.x
1251
+ - ✅ Navegadores modernos (Chrome, Firefox, Safari, Edge)
1252
+ - ✅ iOS Safari 12+
1253
+ - ✅ Chrome Mobile
1254
+ - ✅ Suporte SSR/SSG (com hydration de portals)
1255
+
1256
+ ### Roadmap Futuro
1257
+
1258
+ Melhorias planejadas:
1259
+ - Indicador visual de scroll (mais ações disponíveis)
1260
+ - Posicionamento customizável (top/bottom)
1261
+ - Temas customizados
1262
+ - Suporte a ações agrupadas (dropdowns)
1263
+ - Contador animado ao mudar seleção
1264
+ - Undo/Redo de ações
1265
+ - Modo compacto para mobile
1266
+
1267
+ ***
1268
+
1269
+ ## Resumo da Release
1270
+
1271
+ ### Breaking Changes
1272
+ - ❌ **OTPInput** removido e substituído por **PinInput**
1273
+ - ❌ **Toast (Radix)** removido e substituído por **Toast (Sonner)**
1274
+ - ❌ **SelectionBar** reescrito completamente com arquitetura composicional
1275
+
1276
+ ### Novas Funcionalidades
1277
+ - ✅ **PinInput**: Componente moderno com auto-submit, callbacks e validação
1278
+ - ✅ **Message**: Sistema de mensagens contextuais com 4 variantes
1279
+ - ✅ **Toast**: Sistema de notificações baseado em Sonner com controle de ciclo de vida
1280
+ - ✅ **SelectionBar**: Barra de ações flutuante com portal e estado gerenciado
1281
+ - ✅ **MessageAction**: Componente de ação para Message e Toast
1282
+
1283
+ ### Melhorias
1284
+ - 📖 Documentação completa no Storybook (40 stories no total)
1285
+ - 🎨 Design consistente com tokens do sistema
1286
+ - ♿ Acessibilidade aprimorada em todos os componentes
1287
+ - ⚡ Performance otimizada com memoização e portals
1288
+ - 📦 TypeScript completo com tipos exportados
1289
+ - 🔄 Reutilização de componentes (Toast usa Message internamente)
1290
+ - 📱 Mobile-friendly (swipe no Toast, overflow no SelectionBar)
1291
+ - 🎯 Controle total de ciclo de vida (toasts e selection bar)
1292
+ - 🎭 Animações suaves em todos os componentes
1293
+
1294
+ ### Arquivos Modificados/Criados
1295
+ - 5 arquivos do componente PinInput
1296
+ - 6 arquivos do componente Message (incluindo MessageAction)
1297
+ - 4 arquivos do componente Toast
1298
+ - 6 arquivos do componente SelectionBar
1299
+ - 3 arquivos de stories no Storybook
1300
+ - 1 README do PinInput
1301
+
1302
+ ### Arquivos Removidos
1303
+ - 1 arquivo do OTPInput antigo
1304
+ - 1 arquivo do Toast antigo (Radix)
1305
+ - 1 arquivo do SelectionBar antigo
1306
+ - 1 arquivo de stories do OTPInput
1307
+
1308
+ ### Dependências Adicionadas
1309
+ - **sonner**: ^2.0.7 (~10KB) - Library moderna para toasts
1310
+
1311
+ ### Estatísticas da Release
1312
+ - **Componentes novos/reescritos**: 4 (PinInput, Message, Toast, SelectionBar)
1313
+ - **Componentes removidos**: 3 (OTPInput, Toast Radix, SelectionBar antigo)
1314
+ - **Stories no Storybook**: 40 (9 PinInput + 10 Message + 13 Toast + 8 SelectionBar)
1315
+ - **Breaking changes**: 3 (OTPInput → PinInput, Toast Radix → Toast Sonner, SelectionBar reescrito)
1316
+ - **Linhas de código**: ~1800 novas linhas
1317
+ - **Cobertura de casos de uso**: 37+ casos diferentes
1318
+ - **Funcionalidades do Toast**: 3 métodos (dispatch, dismiss, clear)
1319
+ - **Componentes no SelectionBar**: 6 componentes especializados
1320
+
1321
+ ### Próximos Passos Recomendados
1322
+ 1. **Migrar de OTPInput para PinInput**
1323
+ - Atualizar imports: `@xjur-ui/react/pin-input`
1324
+ - Renomear componentes: `OTPInputRoot` → `PinInput`, etc.
1325
+ - Ajustar props: `initial` → `defaultValue`
1326
+ - Adicionar callbacks opcionais: `onComplete`, `onChangeValue`
1327
+ - Aproveitar auto-submit para melhor UX
1328
+ 2. **Migrar de Toast Radix para Toast Sonner**
1329
+ - Atualizar imports: `@xjur-ui/react/toast`
1330
+ - Substituir `<ToastProvider>` por `<ToastWrapper />`
1331
+ - Converter de API declarativa para imperativa
1332
+ - Usar `toast.dispatch()` ao invés de componentes JSX
1333
+ - Aproveitar `toast.dismiss()` e `toast.clear()` para controle avançado
1334
+ - Armazenar IDs retornados por `dispatch()` quando necessário
1335
+ - Remover lógica de gerenciamento manual de toasts
1336
+ 3. **Integrar Message no sistema**
1337
+ - Substituir alerts antigos por Message
1338
+ - Padronizar feedback de ações em formulários
1339
+ - Implementar em fluxos críticos
1340
+ - Usar MessageAction para ações contextuais
1341
+ 4. **Migrar SelectionBar**
1342
+ - Atualizar imports para componentes composicionais
1343
+ - Converter props de array para JSX composicional
1344
+ - Adicionar `<div id="selection-bar-root" />` no root da aplicação (opcional)
1345
+ - Usar `onOpenChange` para sincronizar estado com seleções
1346
+ - Aproveitar overflow horizontal para muitas ações
1347
+ 5. **Integrar Toast para notificações**
1348
+ - Adicionar `<ToastWrapper />` no root da aplicação
1349
+ - Substituir notificações antigas por `toast.dispatch()`
1350
+ - Usar `toast.dismiss()` para substituir loading por sucesso
1351
+ - Usar `toast.clear()` ao mudar de página/contexto
1352
+ - Implementar callbacks para analytics
1353
+ - Configurar posicionamento adequado
1354
+ - Armazenar IDs para controle de toasts relacionados
1355
+ 6. **Integrar SelectionBar em tabelas e listas**
1356
+ - Adicionar ao componente de seleção múltipla
1357
+ - Sincronizar estado de seleções com `onOpenChange`
1358
+ - Implementar ações em lote (exportar, deletar, arquivar)
1359
+ - Configurar portal root para melhor controle
1360
+ - Testar overflow em mobile
1361
+ 7. **Testar em produção**
1362
+ - Validar acessibilidade com leitores de tela
1363
+ - Verificar performance em dispositivos low-end
1364
+ - Testar gestures em mobile (swipe to dismiss, overflow horizontal)
1365
+ - Validar portals em SSR/SSG
1366
+ - Coletar feedback de usuários
1367
+ - Monitorar métricas de uso
1368
+
1369
+ ### Impacto Estimado
1370
+
1371
+ **Positivo:**
1372
+ - ✅ Melhor DX com API simplificada
1373
+ - ✅ Componentes mais modernos e performáticos
1374
+ - ✅ Documentação muito mais completa
1375
+ - ✅ Consistência visual total entre Message e Toast
1376
+ - ✅ Redução de bundle size (Sonner vs Radix Toast)
1377
+ - ✅ Mais casos de uso suportados
1378
+
1379
+ **Atenção Necessária:**
1380
+ - ⚠️ Migração necessária em todos os usos de OTPInput
1381
+ - ⚠️ Migração necessária em todos os usos de Toast
1382
+ - ⚠️ Migração necessária em todos os usos de SelectionBar
1383
+ - ⚠️ Testes extensivos recomendados (especialmente portals em SSR)
1384
+ - ⚠️ Atualização de documentação interna da equipe
1385
+ - ⚠️ Validação de z-index em diferentes contextos
1386
+
1387
+ ### Guias de Migração Rápida
1388
+
1389
+ #### OTPInput → PinInput (1 minuto)
1390
+
1391
+ ```diff
1392
+ - import { OTPInputRoot, OTPInputInput, ... } from '@xjur-ui/react/otp-input'
1393
+ + import { PinInput, PinInputControl, ... } from '@xjur-ui/react/pin-input'
1394
+
1395
+ - <OTPInputRoot initial="1234" length={4}>
1396
+ + <PinInput defaultValue="1234" length={4} name="code">
1397
+ <PinInputTrigger>
1398
+ - <OTPInputInput index={0} />
1399
+ + <PinInputControl index={0} />
1400
+ </PinInputTrigger>
1401
+ - <OTPInputHiddenInput name="code" />
1402
+ </PinInput>
1403
+ ```
1404
+
1405
+ #### Toast Radix → Toast Sonner (30 segundos)
1406
+
1407
+ ```diff
1408
+ - import { ToastProvider, ToastComponent } from '@xjur-ui/react/toast'
1409
+ + import { ToastWrapper, toast } from '@xjur-ui/react/toast'
1410
+
1411
+ // No root
1412
+ - <ToastProvider>
1413
+ - <App />
1414
+ - </ToastProvider>
1415
+ + <ToastWrapper />
1416
+ + <App />
1417
+
1418
+ // Ao disparar
1419
+ - <ToastComponent variant="success" description="Salvo!" />
1420
+ + toast.dispatch('Salvo!', { variant: 'primary' })
1421
+
1422
+ // Controle avançado
1423
+ + const id = toast.dispatch('Processando...')
1424
+ + toast.dismiss(id) // Fechar específico
1425
+ + toast.clear() // Fechar todos
1426
+ ```
1427
+
1428
+ #### SelectionBar Antigo → SelectionBar Composicional (2 minutos)
1429
+
1430
+ ```diff
1431
+ - import { SelectionBar } from '@xjur-ui/react/selection-bar'
1432
+ + import {
1433
+ + SelectionBarRoot,
1434
+ + SelectionBarTitleRoot,
1435
+ + SelectionBarTitle,
1436
+ + SelectionBarClose,
1437
+ + SelectionBarActionGroup,
1438
+ + SelectionBarAction
1439
+ + } from '@xjur-ui/react/selection-bar'
1440
+
1441
+ - <SelectionBar
1442
+ - title="3 selecionados"
1443
+ - actions={[
1444
+ - { label: 'Exportar', onClick: handleExport },
1445
+ - { label: 'Excluir', onClick: handleDelete }
1446
+ - ]}
1447
+ - />
1448
+ + <SelectionBarRoot>
1449
+ + <SelectionBarTitleRoot>
1450
+ + <SelectionBarClose />
1451
+ + <SelectionBarTitle>3 selecionados</SelectionBarTitle>
1452
+ + </SelectionBarTitleRoot>
1453
+ +
1454
+ + <SelectionBarActionGroup>
1455
+ + <SelectionBarAction onClick={handleExport}>
1456
+ + Exportar
1457
+ + </SelectionBarAction>
1458
+ + <SelectionBarAction
1459
+ + variant="destructive"
1460
+ + onClick={handleDelete}
1461
+ + >
1462
+ + Excluir
1463
+ + </SelectionBarAction>
1464
+ + </SelectionBarActionGroup>
1465
+ + </SelectionBarRoot>
1466
+
1467
+ // Com controle de estado
1468
+ + <SelectionBarRoot
1469
+ + open={open}
1470
+ + onOpenChange={(newOpen) => {
1471
+ + setOpen(newOpen)
1472
+ + if (!newOpen) setSelectedItems([])
1473
+ + }}
1474
+ + >
1475
+ ```
14
1476
 
15
1477
  ## 3.1.1
16
1478