react-lgpd-consent 0.4.1 → 0.4.3

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 CHANGED
@@ -4,9 +4,88 @@ Todas as mudanças notáveis neste projeto serão documentadas neste arquivo.
4
4
 
5
5
  O formato é baseado em [Keep a Changelog](https://keepachangelog.com/pt-BR/1.0.0/), e este projeto segue [Semantic Versioning](https://semver.org/lang/pt-BR/).
6
6
 
7
+ ## [0.4.3] - 2025-10-06 — Otimizações de Performance e Qualidade
8
+
9
+ ### 🚀 **Melhorias de Performance**
10
+
11
+ - **React.memo**: Adicionado memoização em componentes puros (`Branding`, `FloatingPreferencesButton`)
12
+ - **useMemo**: Otimizado cálculo de `positionStyles` no `FloatingPreferencesButton`
13
+ - **Lazy Loading Expandido**: `FloatingPreferencesButton` agora é carregado sob demanda
14
+ - **Logger em Produção**: `warn()`, `info()`, `debug()` suprimidos em `NODE_ENV=production`
15
+ - Reduz overhead em bundle de produção
16
+ - `error()` permanece ativo para debugging crítico
17
+
18
+ ### 🐛 **Correções Críticas**
19
+
20
+ - **ConsentProvider Suspense Bug**: Corrigido crash silencioso quando `consented=true`
21
+ - Adicionado `<React.Suspense>` ausente ao redor do `FloatingPreferencesButton` lazy
22
+ - Sintoma: Provider renderizava `<div />` vazio ao invés de `children`
23
+ - Impacto: Testes com `initialState.consented=true` agora passam
24
+
25
+ ### 🧪 **Testes de Acessibilidade (A11y)**
26
+
27
+ - **jest-axe**: Integração completa com validação WCAG automática
28
+ - **CookieBanner.a11y.test.tsx**: 3 cenários de acessibilidade validados
29
+ - **PreferencesModal.a11y.test.tsx**: 3 cenários de acessibilidade validados
30
+ - **TypeScript**: Definições `jest-axe.d.ts` para matcher `toHaveNoViolations()`
31
+ - **Script**: Adicionado `npm run test:a11y` para testes focados
32
+
33
+ ### 📦 **Exports Modulares**
34
+
35
+ - **`./integrations`**: Novo export separado para tree-shaking otimizado
36
+ - Permite `import { createGoogleAnalyticsIntegration } from 'react-lgpd-consent/integrations'`
37
+ - Reduz bundle para consumidores que não usam integrações
38
+ - Suporte ESM + CJS + TypeScript definitions
39
+
40
+ ### 🔧 **CI/CD**
41
+
42
+ - **Node.js 20**: Atualizado de Node 18 para Node 20 LTS em todos os workflows
43
+ - **Cache TypeScript**: Adicionado cache de builds para acelerar CI (~20% mais rápido)
44
+ - Cache de `.tsbuildinfo`, `node_modules/.cache`, `.eslintcache`
45
+ - Workflows atualizados: `ci.yml`, `codeql.yml`, `deploy-docs.yml`, `package-check.yml`
46
+
47
+ ### 📚 **Documentação**
48
+
49
+ - **Badges**: Adicionados 3 badges ao README (Coverage, Bundle Size, Node Version)
50
+ - Codecov para visualização de cobertura
51
+ - Bundlephobia para tamanho de bundle
52
+ - Node.js badge para requisitos de ambiente
53
+
54
+ ### ✅ **Validação de Qualidade**
55
+
56
+ - **222 testes passando**: 100% de sucesso sem skips
57
+ - **94.85% cobertura**: Mantida cobertura alta
58
+ - **0 warnings de lint**: ESLint limpo
59
+ - **Build otimizado**: ESM 32.52 KB + lazy chunks (95B + 86B)
60
+
61
+ ### 📦 **Otimizações de Bundle**
62
+
63
+ - **tsup.config.ts**: Configuração otimizada para tree-shaking e code-splitting
64
+ - **ESM Bundle**: 33.26 KB → 32.52 KB (-740B, -2.2%)
65
+ - **CJS Bundle**: 118.51 KB → 37.71 KB (CJS principal) + chunks (-68%, muito mais eficiente!)
66
+ - **Brotli Compressed**:
67
+ - ESM: 17.06 KB → 16.95 KB (-110B)
68
+ - CJS: 68.72 KB → 18.02 KB (-74%, -50.7 KB!)
69
+ - **Side-effects**: Configuração refinada para preservar code-splitting sem warnings
70
+ - **Tree-shaking**: Agressivo com external de peer dependencies
71
+
72
+ ### 🎯 **Decisões de Design**
73
+
74
+ - **ConsentGate não usa memo**: Decisão intencional - estado de preferências é dinâmico
75
+ - Re-renders necessários quando usuário altera consentimento
76
+ - Lógica leve o suficiente para não justificar memoização
77
+
78
+ ### 📋 **Dependências**
79
+
80
+ - **Adicionadas**:
81
+ - `@axe-core/react@^4.10.2` (dev)
82
+ - `jest-axe@^10.0.0` (dev)
83
+ - `@types/jest-axe@^3.5.9` (dev)
84
+
7
85
  ## [0.4.1] - 2025-09-21 — Expansão das Integrações Nativas de Scripts
8
86
 
9
87
  ### 🚀 **Integrações Nativas Expandidas**
88
+
10
89
  - **Facebook Pixel**: `createFacebookPixelIntegration()` com auto-tracking e advanced matching
11
90
  - **Hotjar**: `createHotjarIntegration()` para heatmaps e session recordings
12
91
  - **Mixpanel**: `createMixpanelIntegration()` com configuração avançada de eventos
@@ -17,18 +96,21 @@ O formato é baseado em [Keep a Changelog](https://keepachangelog.com/pt-BR/1.0.
17
96
  - **Freshchat**: `createFreshchatIntegration()` para customer support
18
97
 
19
98
  ### 🎯 **Sistema de Configuração em Lote**
99
+
20
100
  - **Templates de negócio**: `createECommerceIntegrations()`, `createSaaSIntegrations()`, `createCorporateIntegrations()`
21
101
  - **Categorização inteligente**: `suggestCategoryForScript()` para sugestão automática de categorias
22
102
  - **Configuração unificada**: Setup simplificado para múltiplas ferramentas com um comando
23
103
  - **Padrões de mercado**: Templates baseados em necessidades reais do mercado brasileiro
24
104
 
25
105
  ### 🔧 **Melhorias no Sistema de Scripts**
106
+
26
107
  - **Validação robusta**: `validateNecessaryClassification()` corrigida para evitar falsos positivos
27
108
  - **Auto-configuração**: `autoConfigureCategories()` com detecção inteligente de categorias necessárias
28
109
  - **Error handling**: Melhor tratamento de erros em carregamento de scripts
29
110
  - **Performance**: Carregamento otimizado e lazy loading de integrações
30
111
 
31
112
  ### 🔍 **Descoberta Automática de Cookies (Experimental)**
113
+
32
114
  - **discoverRuntimeCookies()**: Escaneamento de cookies em tempo real no navegador
33
115
  - **detectConsentCookieName()**: Detecção automática do cookie de consentimento
34
116
  - **categorizeDiscoveredCookies()**: Categorização inteligente usando padrões LGPD
@@ -36,17 +118,20 @@ O formato é baseado em [Keep a Changelog](https://keepachangelog.com/pt-BR/1.0.
36
118
  - **SSR-safe**: Funciona corretamente em ambientes server-side rendering
37
119
 
38
120
  ### 🎨 **Design Tokens Expandidos**
121
+
39
122
  - **200+ pontos de customização**: Expansão dramática do sistema de design tokens
40
123
  - **Sistema responsivo**: Breakpoints, spacing responsivo, typography hierarchy
41
124
  - **Acessibilidade nativa**: Contrast ratios, focus states, motion preferences
42
125
  - **Tokens por componente**: Customização granular para cada elemento UI
43
126
 
44
127
  ### 📝 **Sistema Avançado de Textos**
128
+
45
129
  - **Templates pré-configurados**: Ecommerce, SaaS, Governo com contextos específicos
46
130
  - **Multilingual**: Português, inglês, espanhol com fallbacks inteligentes
47
131
  - **Função resolveTexts**: Resolução automática de textos baseada em contexto
48
132
 
49
133
  ### 🧪 **Melhorias de Testes e Qualidade**
134
+
50
135
  - **193 testes passando**: Cobertura substancialmente melhorada
51
136
  - **19 novos testes**: Especificamente para `cookieRegistry` (antes 45.83% → 100% branches)
52
137
  - **Test realism**: Testes adaptados ao comportamento real vs ideal
@@ -54,6 +139,7 @@ O formato é baseado em [Keep a Changelog](https://keepachangelog.com/pt-BR/1.0.
54
139
  - **Lint compliance**: Configuração ESLint mais rigorosa e aderente
55
140
 
56
141
  ### 🔧 **Melhorias de API e Developer Experience**
142
+
57
143
  - **Exports organizados**: Melhor estruturação das exportações públicas
58
144
  - **TypeScript strict**: Tipagem mais rigorosa e descritiva
59
145
  - **Documentação TSDoc**: Comentários expandidos com exemplos práticos
@@ -61,12 +147,14 @@ O formato é baseado em [Keep a Changelog](https://keepachangelog.com/pt-BR/1.0.
61
147
  - **Performance**: Otimizações em carregamento e renderização
62
148
 
63
149
  ### 📚 **Exemplos e Migração**
150
+
64
151
  - **MigrationDemo-v0.4.1.tsx**: Exemplo completo mostrando todas as novidades
65
152
  - **Remoção**: TestV0.3.1.tsx removido (obsoleto)
66
153
  - **Compatibilidade**: Guias de migração antes/depois
67
154
  - **Best practices**: Demonstrações de uso avançado
68
155
 
69
156
  ### 🏗️ **Build e Infraestrutura**
157
+
70
158
  - **Bundle otimizado**: ESM 34.36 KB, CJS 102.74 KB
71
159
  - **Tree-shaking**: Configuração `sideEffects: false` otimizada
72
160
  - **Docs geradas**: TypeDoc atualizado com novas funcionalidades
@@ -74,22 +162,25 @@ O formato é baseado em [Keep a Changelog](https://keepachangelog.com/pt-BR/1.0.
74
162
 
75
163
  ### ⚠️ **Breaking Changes**
76
164
 
77
- #### 🔧 **`setPreference` Type Change**
165
+ #### 🔧 **`setPreference` Type Change**
166
+
78
167
  - **Mudança**: `setPreference(cat: Category, value: boolean)` → `setPreference(cat: string, value: boolean)`
79
- - **Motivo**: Suporte a categorias customizadas além das predefinidas
168
+ - **Motivo**: Suporte a categorias customizadas além das predefinidas
80
169
  - **Impacto**: Código TypeScript com tipo `Category` explícito pode precisar ajustes
81
- - **Migração**:
170
+ - **Migração**:
82
171
  - ✅ **Nenhuma mudança necessária** se usando strings literais (`'analytics'`, `'marketing'`)
83
172
  - ⚠️ **Ajuste necessário** apenas se estava usando explicitamente o tipo `Category`
84
173
  - 📚 **Guia**: Use `string` para suportar categorias customizadas ou continue usando os valores padrão
85
174
 
86
175
  #### 🔧 **`ScriptIntegration.category` Type Change**
176
+
87
177
  - **Mudança**: `category: Category` → `category: string`
88
178
  - **Motivo**: Suporte a categorias customizadas nas integrações de script
89
179
  - **Impacto**: Integrações customizadas com tipo `Category` explícito
90
180
  - **Migração**: Mesmas diretrizes do `setPreference` acima
91
181
 
92
182
  ### 🎯 **Categorias Suportadas**
183
+
93
184
  - `necessary` (sempre ativo)
94
185
  - `analytics` (Google Analytics, etc.)
95
186
  - `marketing` (Facebook Pixel, Google Ads)
@@ -98,6 +189,7 @@ O formato é baseado em [Keep a Changelog](https://keepachangelog.com/pt-BR/1.0.
98
189
  - `personalization` (Preferências, customização)
99
190
 
100
191
  ### 📈 **Estatísticas de Melhoria**
192
+
101
193
  - **Design Tokens**: 4 → 200+ pontos de customização (+4900%)
102
194
  - **Testes**: 174 → 193 testes (+11% cobertura)
103
195
  - **Funcionalidades**: +15 novas funções exportadas
@@ -107,6 +199,7 @@ O formato é baseado em [Keep a Changelog](https://keepachangelog.com/pt-BR/1.0.
107
199
  ## [0.4.0] - 2025-09-09 — Custom categories
108
200
 
109
201
  ### Added
202
+
110
203
  - Support for `customCategories` in `ConsentProvider.categories`.
111
204
  - Included in preferences initialization and validation.
112
205
  - Shown in the Preferences modal (with name/description).
@@ -115,6 +208,7 @@ O formato é baseado em [Keep a Changelog](https://keepachangelog.com/pt-BR/1.0.
115
208
  - Storybook story: WithCustomCategories.
116
209
 
117
210
  ### Notes
211
+
118
212
  - Non-breaking change; existing configurations continue to work.
119
213
 
120
214
  ## [0.3.7] - 2025-09-08 - Testes de UI e carregamento de scripts
@@ -656,3 +750,35 @@ A v0.2.1 introduz um **sistema inteligente de orientações** que guia desenvolv
656
750
  - [ ] Base legal por categoria
657
751
  - [ ] Relatórios de compliance
658
752
  - [ ] Templates por setor
753
+
754
+ ## [0.4.2] - 06/10/2025 — Quickstarts + SSR Guide + Validação (DEV)
755
+
756
+ ### ✨ Quickstarts executáveis
757
+
758
+ - Next.js (App Router) e Vite com Consent Mode v2 integrado e bloqueio real de scripts (GTM/GA4 não carregam antes do consentimento).
759
+ - Seções no QUICKSTART.md com passos copy‑paste e validação do comportamento esperado.
760
+
761
+ ### 🧱 Guia SSR/Next.js (App Router)
762
+
763
+ - Padrões seguros para evitar hydration mismatch: wrapper client‑only com `'use client'` e `dynamic({ ssr: false })`, efeitos que acessam `window/document` apenas no cliente.
764
+ - Ordem de provedores/estilos (Emotion/MUI) e z-index/portals documentados (overlay 1299, modais ≥ 1300).
765
+
766
+ ### ✅ Validação de configuração do ConsentProvider (DEV)
767
+
768
+ - Validação com Zod em desenvolvimento (import dinâmico) e sanitização leve em produção.
769
+ - Mensagens amigáveis: alerta quando `categories` não é fornecida; remove `'necessary'` de `enabledCategories`; detecta duplicidades/valores inválidos; valida `customCategories`.
770
+ - Testes cobrindo casos inválidos e asserts de mensagens.
771
+
772
+ ### 📚 Categorias — definição, uso e exemplos
773
+
774
+ - Fonte única de verdade: `ConsentProvider.categories`. UI, hooks e integrações leem a mesma definição.
775
+ - Esclarecimento: apenas “necessários” é obrigatório; demais categorias são opcionais conforme o negócio.
776
+ - Exemplos mínimo (somente necessários) e completo (analytics/marketing/functional).
777
+
778
+ ### 🔧 Dependências
779
+
780
+ - Adicionado: `zod@^3.23.8` (usado somente em DEV via import dinâmico; não impacta o bundle de produção).
781
+
782
+ ### 🧩 Sem breaking changes
783
+
784
+ - Alterações são compatíveis; padrões seguros preservados.
package/QUICKSTART.md CHANGED
@@ -62,9 +62,263 @@ export default App
62
62
 
63
63
  ````
64
64
 
65
+ ## ⚡ Quickstarts: Next.js (App Router) e Vite
66
+
67
+ Os exemplos a seguir integram GTM/GA4 com Consent Mode v2 e garantem que nenhum script de tracking rode antes do consentimento. Eles também mostram como usar `ConsentScriptLoader` e sincronizar os sinais do Consent Mode via `gtag('consent', ...)`.
68
+
69
+ - Exemplos completos: `examples/next-app-router/*`, `examples/vite/*`
70
+
71
+ ### Next.js 14/15 — App Router (SSR-safe)
72
+
73
+ 1) Criar app Next e instalar deps
74
+
75
+ ```bash
76
+ npm create next-app@latest my-app --ts --eslint --src-dir --app --no-tailwind --no-experimental-app
77
+ cd my-app
78
+ npm i react-lgpd-consent @mui/material @mui/icons-material @emotion/react @emotion/styled
79
+ ```
80
+
81
+ 2) Variáveis públicas no `.env.local`
82
+
83
+ ```
84
+ NEXT_PUBLIC_GA_ID=G-XXXXXXXXXX
85
+ NEXT_PUBLIC_GTM_ID=GTM-XXXXXXX
86
+ ```
87
+
88
+ 3) Copiar os arquivos do exemplo e ajustar imports
89
+
90
+ - De `examples/next-app-router/app/layout.tsx` → `app/layout.tsx`
91
+ - De `examples/next-app-router/app/page.tsx` → `app/page.tsx`
92
+ - De `examples/next-app-router/components/ClientConsent.tsx` → `app/components/ClientConsent.tsx`
93
+
94
+ Observação: nos arquivos copiados, troque imports relativos para `import { ConsentProvider, ConsentScriptLoader } from 'react-lgpd-consent'`.
95
+
96
+ 4) O que esse setup faz
97
+
98
+ - `ClientConsent` é um componente client-only (via `dynamic(..., { ssr: false })` no layout) que:
99
+ - Injeta um stub de `dataLayer/gtag` e define `consent default = denied` para todos os sinais (ad_storage, ad_user_data, ad_personalization, analytics_storage).
100
+ - Sincroniza as mudanças do consentimento com `gtag('consent','update', ...)` mapeando as categorias: `analytics → analytics_storage`, `marketing → ad_*`.
101
+ - Usa `ConsentScriptLoader` para carregar GTM/GA4 somente quando as categorias permitirem. Antes disso, nenhum script de tracking é carregado.
102
+
103
+ 5) Rodar
104
+
105
+ ```bash
106
+ npm run dev
107
+ ```
108
+
109
+ Validação rápida:
110
+ - Acesse em aba anônima: a rede não carrega `gtm.js`/`gtag/js` até aceitar preferências.
111
+ - Ao aceitar `analytics`, o GA4 é carregado; ao aceitar `marketing`, os sinais `ad_*` são atualizados como granted.
112
+
113
+ ### Vite (CSR)
114
+
115
+ 1) Criar app Vite e instalar deps
116
+
117
+ ```bash
118
+ npm create vite@latest my-app -- --template react-ts
119
+ cd my-app
120
+ npm i react-lgpd-consent @mui/material @mui/icons-material @emotion/react @emotion/styled
121
+ ```
122
+
123
+ 2) Variáveis no `.env`
124
+
125
+ ```
126
+ VITE_GA_ID=G-XXXXXXXXXX
127
+ VITE_GTM_ID=GTM-XXXXXXX
128
+ ```
129
+
130
+ 3) Copiar os arquivos do exemplo e ajustar imports
131
+
132
+ - De `examples/vite/index.html` → `index.html` (não adicione scripts do GA/GTM aqui)
133
+ - De `examples/vite/src/main.tsx` → `src/main.tsx`
134
+ - De `examples/vite/src/App.tsx` → `src/App.tsx`
135
+ - De `examples/vite/src/consent/GtagConsent.tsx` → `src/consent/GtagConsent.tsx`
136
+
137
+ Observação: nos arquivos copiados, troque imports relativos para `import { ... } from 'react-lgpd-consent'`.
138
+
139
+ 4) Rodar
140
+
141
+ ```bash
142
+ npm run dev
143
+ ```
144
+
145
+ Validação rápida:
146
+ - Ao abrir a app (em nova sessão), nenhum script de tracking é baixado até que o usuário consinta.
147
+ - Preferências atualizam `gtag('consent','update', ...)` corretamente por categoria.
148
+
65
149
  ## 🧩 Categorias customizadas (customCategories)
66
150
  Disponível a partir da v0.4.0.
67
151
 
152
+ ## 🍪 Categorias: definição, uso e exemplos
153
+
154
+ Fonte única de verdade
155
+ - Defina as categorias do seu projeto SOMENTE na prop `categories` do `ConsentProvider`.
156
+ - A UI (Banner/Modal), os hooks (`useConsent`, `useCategories`) e as integrações (`ConsentScriptLoader`) leem a mesma definição. Não declare categorias em outros lugares.
157
+
158
+ O que é obrigatório?
159
+ - Apenas a categoria `necessary` é obrigatória (e já é sempre incluída automaticamente).
160
+ - Todas as demais (`analytics`, `marketing`, `functional`, etc.) são opcionais e dependem do seu caso de negócio. Se você não usa analytics/ads/chat, simplesmente não habilite essas categorias.
161
+
162
+ Como “esconder” categorias que não uso?
163
+ - Basta não incluí-las em `enabledCategories` e não declará-las em `customCategories`. A UI não exibirá toggles para categorias ausentes.
164
+
165
+ Exemplo A — Somente necessários (mínimo, comum para apps internos/governo sem tracking)
166
+ ```tsx
167
+ import { ConsentProvider } from 'react-lgpd-consent'
168
+
169
+ export default function App() {
170
+ return (
171
+ <ConsentProvider
172
+ categories={{ enabledCategories: [] }}
173
+ texts={{ bannerMessage: 'Usamos apenas cookies necessários para funcionamento.' }}
174
+ >
175
+ <YourApp />
176
+ </ConsentProvider>
177
+ )
178
+ }
179
+ ```
180
+
181
+ Exemplo B — Conjunto completo (site com analytics e marketing)
182
+ ```tsx
183
+ import { ConsentProvider } from 'react-lgpd-consent'
184
+
185
+ export default function App() {
186
+ return (
187
+ <ConsentProvider
188
+ categories={{ enabledCategories: ['analytics', 'marketing', 'functional'] }}
189
+ >
190
+ <YourApp />
191
+ </ConsentProvider>
192
+ )
193
+ }
194
+ ```
195
+
196
+ Boas práticas
197
+ - Sempre passe `categories` explicitamente. Em DEV, a biblioteca avisa quando `categories` não foi configurado para evitar ambiguidades.
198
+ - Não classifique scripts de analytics/ads como “necessary” — use `ConsentScriptLoader` e categorias adequadas.
199
+ - Em dúvidas, comece com “somente necessários” e evolua quando o negócio exigir outras categorias.
200
+
201
+ ### 🔎 Validação de configuração (DEV)
202
+
203
+ Em desenvolvimento, a biblioteca valida a configuração e mostra mensagens amigáveis no console. Nada disso impacta produção (onde só ocorre uma sanitização leve).
204
+
205
+ Avisos comuns e como corrigir:
206
+ - `Prop 'categories' não fornecida...` — defina `categories.enabledCategories` de forma explícita; exemplo mínimo: `categories={{ enabledCategories: [] }}`.
207
+ - `'necessary' é sempre incluída automaticamente` — remova `'necessary'` de `enabledCategories` (ela já é incluída por padrão).
208
+ - `IDs de categoria duplicados detectados` — revise `enabledCategories` e `customCategories` para garantir que não há IDs repetidos.
209
+ - `enabledCategories contém valores inválidos` — verifique se todos os itens são strings não vazias (IDs de categoria).
210
+ - `customCategories: ... — ... deve ser uma string não vazia` — preencha `id`, `name` e `description` das categorias customizadas.
211
+
212
+ Notas:
213
+ - Validação detalhada roda apenas em `NODE_ENV !== 'production'`.
214
+ - Em produção, a lib não carrega o validador; somente remove `'necessary'` se vier por engano, mantendo o comportamento seguro.
215
+
216
+ ## 🧱 SSR/Next.js (App Router) — Padrões seguros
217
+
218
+ Objetivo: evitar hydration mismatch, hooks em Server Components e vazamento de scripts.
219
+
220
+ Padrões recomendados
221
+ - Envolva o app com o `ConsentProvider` apenas no cliente.
222
+ - Use `dynamic(() => import('./ClientConsent'), { ssr: false })` no `RootLayout` (Server Component) e mova hooks e efeitos para o componente cliente.
223
+ - Nenhum acesso a `window`/`document` no topo de módulo; use apenas dentro de `useEffect`.
224
+ - Inicialize Consent Mode v2 com `gtag('consent','default', denied)` antes de carregar GTM/GA4; depois, atualize sinais na mudança de preferências.
225
+
226
+ Exemplo de RootLayout (Server) + Client wrapper
227
+
228
+ ```tsx
229
+ // app/layout.tsx (Server Component)
230
+ import dynamic from 'next/dynamic'
231
+
232
+ const ClientConsent = dynamic(() => import('./components/ClientConsent'), { ssr: false })
233
+
234
+ export default function RootLayout({ children }: { children: React.ReactNode }) {
235
+ return (
236
+ <html lang="pt-BR">
237
+ <body>
238
+ <ClientConsent>{children}</ClientConsent>
239
+ </body>
240
+ </html>
241
+ )
242
+ }
243
+ ```
244
+
245
+ ```tsx
246
+ // app/components/ClientConsent.tsx (Client Component)
247
+ 'use client'
248
+ import React from 'react'
249
+ import { ConsentProvider, ConsentScriptLoader } from 'react-lgpd-consent'
250
+ import { COMMON_INTEGRATIONS } from 'react-lgpd-consent'
251
+ import { useConsent } from 'react-lgpd-consent'
252
+
253
+ function BootstrapConsentMode() {
254
+ React.useEffect(() => {
255
+ const w = window as any
256
+ w.dataLayer = w.dataLayer ?? []
257
+ w.gtag = w.gtag ?? ((...args: any[]) => w.dataLayer.push(args))
258
+ w.gtag('consent', 'default', {
259
+ ad_storage: 'denied',
260
+ ad_user_data: 'denied',
261
+ ad_personalization: 'denied',
262
+ analytics_storage: 'denied',
263
+ })
264
+ }, [])
265
+ return null
266
+ }
267
+
268
+ function SyncConsentMode() {
269
+ const { consented, preferences } = useConsent()
270
+ React.useEffect(() => {
271
+ if (!consented) return
272
+ const w = window as any
273
+ w.gtag?.('consent', 'update', {
274
+ analytics_storage: preferences.analytics ? 'granted' : 'denied',
275
+ ad_storage: preferences.marketing ? 'granted' : 'denied',
276
+ ad_user_data: preferences.marketing ? 'granted' : 'denied',
277
+ ad_personalization: preferences.marketing ? 'granted' : 'denied',
278
+ })
279
+ }, [consented, preferences])
280
+ return null
281
+ }
282
+
283
+ export default function ClientConsent({ children }: { children: React.ReactNode }) {
284
+ const GA = process.env.NEXT_PUBLIC_GA_ID!
285
+ const GTM = process.env.NEXT_PUBLIC_GTM_ID!
286
+ return (
287
+ <ConsentProvider categories={{ enabledCategories: ['analytics', 'marketing', 'functional'] }} blocking>
288
+ <BootstrapConsentMode />
289
+ <SyncConsentMode />
290
+ <ConsentScriptLoader
291
+ integrations={[
292
+ COMMON_INTEGRATIONS.googleAnalytics({ measurementId: GA }),
293
+ COMMON_INTEGRATIONS.googleTagManager({ containerId: GTM }),
294
+ ]}
295
+ />
296
+ {children}
297
+ </ConsentProvider>
298
+ )
299
+ }
300
+ ```
301
+
302
+ Ordem de provedores e estilos (MUI/Emotion)
303
+ - Preferência de ordem recomendada:
304
+ - `CacheProvider` (Emotion) ou `StyledEngineProvider` com `injectFirst`
305
+ - `ThemeProvider` (MUI)
306
+ - `CssBaseline`
307
+ - `ConsentProvider` (sem criar tema por padrão)
308
+ - Motivo: garante injeção de estilos do MUI antes de CSS da app e evita desalinhamento visual; os componentes da lib herdam o tema quando presente.
309
+
310
+ Z-index e Portals
311
+ - Componentes MUI usam o `zIndex` do tema; modals/portals padrão usam `zIndex.modal = 1300`.
312
+ - O overlay bloqueante do Provider usa `z-index: 1299`; o Modal/Banner usa camadas ≥ 1300.
313
+ - Em caso de conflito com headers fixos, ajuste o `theme.zIndex` (ex.: `appBar: 1200`, `modal: 1300+`) ou os `designTokens` conforme a necessidade.
314
+
315
+ Checklist SSR (evite hydration mismatch)
316
+ - [ ] Hooks somente em Client Components (`'use client'` no topo).
317
+ - [ ] Nada de `window`/`document`/`localStorage` no topo de módulo (apenas em `useEffect`).
318
+ - [ ] `dynamic(..., { ssr: false })` para wrappers que usam hooks e efeitos do consentimento.
319
+ - [ ] GTM/GA4 carregados apenas após consentimento (via `ConsentScriptLoader`).
320
+ - [ ] Sem `<script>` de GTM/GA4 em `head`/`body`; todo carregamento vem do loader.
321
+
68
322
  ## 🎨 Dica de estilo: Backdrop sensível ao tema
69
323
 
70
324
  No modo bloqueante, o banner usa um backdrop para focar a atenção do usuário. Você pode controlar via design tokens:
package/README.en.md CHANGED
@@ -15,6 +15,12 @@
15
15
  <a href="https://nextjs.org/"><img src="https://img.shields.io/badge/Next.js-Compatible-000000?style=for-the-badge&logo=next.js&logoColor=white" alt="Next.js Compatible"></a>
16
16
  </div>
17
17
 
18
+ <div>
19
+ <a href="https://codecov.io/gh/lucianoedipo/react-lgpd-consent"><img src="https://img.shields.io/codecov/c/github/lucianoedipo/react-lgpd-consent?style=for-the-badge&logo=codecov&logoColor=white" alt="Coverage"></a>
20
+ <a href="https://bundlephobia.com/package/react-lgpd-consent"><img src="https://img.shields.io/bundlephobia/minzip/react-lgpd-consent?style=for-the-badge&logo=webpack&logoColor=white" alt="Bundle Size"></a>
21
+ <a href="https://nodejs.org"><img src="https://img.shields.io/node/v/react-lgpd-consent?style=for-the-badge&logo=node.js&logoColor=white" alt="Node Version"></a>
22
+ </div>
23
+
18
24
  <br />
19
25
 
20
26
  <p>
package/README.md CHANGED
@@ -15,6 +15,12 @@
15
15
  <a href="https://nextjs.org/"><img src="https://img.shields.io/badge/Next.js-Compatible-000000?style=for-the-badge&logo=next.js&logoColor=white" alt="Next.js Compatible"></a>
16
16
  </div>
17
17
 
18
+ <div>
19
+ <a href="https://codecov.io/gh/lucianoedipo/react-lgpd-consent"><img src="https://img.shields.io/codecov/c/github/lucianoedipo/react-lgpd-consent?style=for-the-badge&logo=codecov&logoColor=white" alt="Coverage"></a>
20
+ <a href="https://bundlephobia.com/package/react-lgpd-consent"><img src="https://img.shields.io/bundlephobia/minzip/react-lgpd-consent?style=for-the-badge&logo=webpack&logoColor=white" alt="Bundle Size"></a>
21
+ <a href="https://nodejs.org"><img src="https://img.shields.io/node/v/react-lgpd-consent?style=for-the-badge&logo=node.js&logoColor=white" alt="Node Version"></a>
22
+ </div>
23
+
18
24
  <br />
19
25
 
20
26
  <p>
@@ -113,6 +119,7 @@ Para mais detalhes sobre customização, hooks e funcionalidades, consulte os se
113
119
  ### 📋 Documentação Principal
114
120
 
115
121
  - **[📚 Guia de Início Rápido (`QUICKSTART.md`)](./QUICKSTART.md)**: Tutorial passo a passo com exemplos práticos, tabela completa de props, debugging e integrações.
122
+ - Seção recomendada: “SSR/Next.js (App Router) — Padrões seguros” com boas práticas de `'use client'`, `dynamic({ ssr: false })` e ordem dos provedores/estilos (MUI/Emotion) para evitar hydration mismatch.
116
123
  - Novo na v0.4.0: suporte a `customCategories` — veja a seção “Categorias customizadas (customCategories)” no Quickstart.
117
124
  - Novo na v0.4.1: integrações nativas para Facebook Pixel, Hotjar, Mixpanel, Clarity, Intercom e Zendesk — veja o guia [INTEGRACOES.md](./INTEGRACOES.md).
118
125
  - Dica: use `designTokens.layout.backdrop: 'auto'` para backdrop sensível ao tema no banner bloqueante.
@@ -0,0 +1,11 @@
1
+ 'use strict';
2
+
3
+ var chunkFJKRAERJ_cjs = require('./chunk-FJKRAERJ.cjs');
4
+ require('./chunk-ORI4PLVG.cjs');
5
+
6
+
7
+
8
+ Object.defineProperty(exports, "FloatingPreferencesButton", {
9
+ enumerable: true,
10
+ get: function () { return chunkFJKRAERJ_cjs.FloatingPreferencesButton; }
11
+ });
@@ -0,0 +1,2 @@
1
+ export { FloatingPreferencesButton } from './chunk-PJFGQMCI.js';
2
+ import './chunk-RWT2ORFE.js';
@@ -0,0 +1,2 @@
1
+ export { PreferencesModal } from './chunk-N3QOW4SA.js';
2
+ import './chunk-RWT2ORFE.js';
@@ -0,0 +1,11 @@
1
+ 'use strict';
2
+
3
+ var chunk25XEI2DZ_cjs = require('./chunk-25XEI2DZ.cjs');
4
+ require('./chunk-ORI4PLVG.cjs');
5
+
6
+
7
+
8
+ Object.defineProperty(exports, "PreferencesModal", {
9
+ enumerable: true,
10
+ get: function () { return chunk25XEI2DZ_cjs.PreferencesModal; }
11
+ });