react-lgpd-consent 0.4.1 → 0.4.4
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 +150 -3
- package/QUICKSTART.md +254 -0
- package/README.en.md +6 -0
- package/README.md +20 -0
- package/dist/FloatingPreferencesButton-4AGBXNHH.cjs +11 -0
- package/dist/FloatingPreferencesButton-IY7TFD7D.js +2 -0
- package/dist/PreferencesModal-5KNHWW57.js +2 -0
- package/dist/PreferencesModal-YBCWCVUI.cjs +11 -0
- package/dist/chunk-25XEI2DZ.cjs +193 -0
- package/dist/chunk-FJKRAERJ.cjs +119 -0
- package/dist/chunk-N3QOW4SA.js +178 -0
- package/dist/chunk-ORI4PLVG.cjs +1899 -0
- package/dist/chunk-PJFGQMCI.js +92 -0
- package/dist/{chunk-VOQUCGOA.js → chunk-RWT2ORFE.js} +340 -522
- package/dist/index.cjs +177 -2286
- package/dist/index.d.cts +12 -2
- package/dist/index.d.ts +12 -2
- package/dist/index.js +10 -98
- package/package.json +47 -41
- package/dist/PreferencesModal-RNRD3JKB.js +0 -6
package/CHANGELOG.md
CHANGED
|
@@ -4,9 +4,109 @@ 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.4] - 2025-10-06 — Correções de CI/CD e Publicação
|
|
8
|
+
|
|
9
|
+
### 🔧 **Correções de CI/CD**
|
|
10
|
+
|
|
11
|
+
- **Workflow de Publicação npm**: Corrigido bug que impedia publicação mesmo quando tag estava na `main`
|
|
12
|
+
- **Problema**: `git fetch --depth=1` limitava histórico e falhava verificação de ancestralidade
|
|
13
|
+
- **Solução**: Removido `--depth=1` do fetch, aproveitando `fetch-depth: 0` do checkout
|
|
14
|
+
- **Impacto**: Tags criadas após merge para `main` agora são publicadas corretamente no npm
|
|
15
|
+
|
|
16
|
+
### 📊 **Integração com Codecov**
|
|
17
|
+
|
|
18
|
+
- **Upload de Coverage**: Adicionado `codecov/codecov-action@v5` ao workflow CI
|
|
19
|
+
- Envia relatórios de cobertura automaticamente para Codecov
|
|
20
|
+
- Token configurado via `secrets.CODECOV_TOKEN`
|
|
21
|
+
- Integração com badge de coverage no README
|
|
22
|
+
|
|
23
|
+
### 📚 **Documentação**
|
|
24
|
+
|
|
25
|
+
- **Badges**: Badge de coverage já configurado no README (v0.4.3) agora recebe dados em tempo real
|
|
26
|
+
- **Workflows**: Documentação inline sobre fetch depth e verificação de ancestralidade
|
|
27
|
+
|
|
28
|
+
## [0.4.3] - 2025-10-06 — Otimizações de Performance e Qualidade
|
|
29
|
+
|
|
30
|
+
### 🚀 **Melhorias de Performance**
|
|
31
|
+
|
|
32
|
+
- **React.memo**: Adicionado memoização em componentes puros (`Branding`, `FloatingPreferencesButton`)
|
|
33
|
+
- **useMemo**: Otimizado cálculo de `positionStyles` no `FloatingPreferencesButton`
|
|
34
|
+
- **Lazy Loading Expandido**: `FloatingPreferencesButton` agora é carregado sob demanda
|
|
35
|
+
- **Logger em Produção**: `warn()`, `info()`, `debug()` suprimidos em `NODE_ENV=production`
|
|
36
|
+
- Reduz overhead em bundle de produção
|
|
37
|
+
- `error()` permanece ativo para debugging crítico
|
|
38
|
+
|
|
39
|
+
### 🐛 **Correções Críticas**
|
|
40
|
+
|
|
41
|
+
- **ConsentProvider Suspense Bug**: Corrigido crash silencioso quando `consented=true`
|
|
42
|
+
- Adicionado `<React.Suspense>` ausente ao redor do `FloatingPreferencesButton` lazy
|
|
43
|
+
- Sintoma: Provider renderizava `<div />` vazio ao invés de `children`
|
|
44
|
+
- Impacto: Testes com `initialState.consented=true` agora passam
|
|
45
|
+
|
|
46
|
+
### 🧪 **Testes de Acessibilidade (A11y)**
|
|
47
|
+
|
|
48
|
+
- **jest-axe**: Integração completa com validação WCAG automática
|
|
49
|
+
- **CookieBanner.a11y.test.tsx**: 3 cenários de acessibilidade validados
|
|
50
|
+
- **PreferencesModal.a11y.test.tsx**: 3 cenários de acessibilidade validados
|
|
51
|
+
- **TypeScript**: Definições `jest-axe.d.ts` para matcher `toHaveNoViolations()`
|
|
52
|
+
- **Script**: Adicionado `npm run test:a11y` para testes focados
|
|
53
|
+
|
|
54
|
+
### 📦 **Exports Modulares**
|
|
55
|
+
|
|
56
|
+
- **`./integrations`**: Novo export separado para tree-shaking otimizado
|
|
57
|
+
- Permite `import { createGoogleAnalyticsIntegration } from 'react-lgpd-consent/integrations'`
|
|
58
|
+
- Reduz bundle para consumidores que não usam integrações
|
|
59
|
+
- Suporte ESM + CJS + TypeScript definitions
|
|
60
|
+
|
|
61
|
+
### 🔧 **CI/CD**
|
|
62
|
+
|
|
63
|
+
- **Node.js 20**: Atualizado de Node 18 para Node 20 LTS em todos os workflows
|
|
64
|
+
- **Cache TypeScript**: Adicionado cache de builds para acelerar CI (~20% mais rápido)
|
|
65
|
+
- Cache de `.tsbuildinfo`, `node_modules/.cache`, `.eslintcache`
|
|
66
|
+
- Workflows atualizados: `ci.yml`, `codeql.yml`, `deploy-docs.yml`, `package-check.yml`
|
|
67
|
+
|
|
68
|
+
### 📚 **Documentação**
|
|
69
|
+
|
|
70
|
+
- **Badges**: Adicionados 3 badges ao README (Coverage, Bundle Size, Node Version)
|
|
71
|
+
- Codecov para visualização de cobertura
|
|
72
|
+
- Bundlephobia para tamanho de bundle
|
|
73
|
+
- Node.js badge para requisitos de ambiente
|
|
74
|
+
|
|
75
|
+
### ✅ **Validação de Qualidade**
|
|
76
|
+
|
|
77
|
+
- **222 testes passando**: 100% de sucesso sem skips
|
|
78
|
+
- **94.85% cobertura**: Mantida cobertura alta
|
|
79
|
+
- **0 warnings de lint**: ESLint limpo
|
|
80
|
+
- **Build otimizado**: ESM 32.52 KB + lazy chunks (95B + 86B)
|
|
81
|
+
|
|
82
|
+
### 📦 **Otimizações de Bundle**
|
|
83
|
+
|
|
84
|
+
- **tsup.config.ts**: Configuração otimizada para tree-shaking e code-splitting
|
|
85
|
+
- **ESM Bundle**: 33.26 KB → 32.52 KB (-740B, -2.2%)
|
|
86
|
+
- **CJS Bundle**: 118.51 KB → 37.71 KB (CJS principal) + chunks (-68%, muito mais eficiente!)
|
|
87
|
+
- **Brotli Compressed**:
|
|
88
|
+
- ESM: 17.06 KB → 16.95 KB (-110B)
|
|
89
|
+
- CJS: 68.72 KB → 18.02 KB (-74%, -50.7 KB!)
|
|
90
|
+
- **Side-effects**: Configuração refinada para preservar code-splitting sem warnings
|
|
91
|
+
- **Tree-shaking**: Agressivo com external de peer dependencies
|
|
92
|
+
|
|
93
|
+
### 🎯 **Decisões de Design**
|
|
94
|
+
|
|
95
|
+
- **ConsentGate não usa memo**: Decisão intencional - estado de preferências é dinâmico
|
|
96
|
+
- Re-renders necessários quando usuário altera consentimento
|
|
97
|
+
- Lógica leve o suficiente para não justificar memoização
|
|
98
|
+
|
|
99
|
+
### 📋 **Dependências**
|
|
100
|
+
|
|
101
|
+
- **Adicionadas**:
|
|
102
|
+
- `@axe-core/react@^4.10.2` (dev)
|
|
103
|
+
- `jest-axe@^10.0.0` (dev)
|
|
104
|
+
- `@types/jest-axe@^3.5.9` (dev)
|
|
105
|
+
|
|
7
106
|
## [0.4.1] - 2025-09-21 — Expansão das Integrações Nativas de Scripts
|
|
8
107
|
|
|
9
108
|
### 🚀 **Integrações Nativas Expandidas**
|
|
109
|
+
|
|
10
110
|
- **Facebook Pixel**: `createFacebookPixelIntegration()` com auto-tracking e advanced matching
|
|
11
111
|
- **Hotjar**: `createHotjarIntegration()` para heatmaps e session recordings
|
|
12
112
|
- **Mixpanel**: `createMixpanelIntegration()` com configuração avançada de eventos
|
|
@@ -17,18 +117,21 @@ O formato é baseado em [Keep a Changelog](https://keepachangelog.com/pt-BR/1.0.
|
|
|
17
117
|
- **Freshchat**: `createFreshchatIntegration()` para customer support
|
|
18
118
|
|
|
19
119
|
### 🎯 **Sistema de Configuração em Lote**
|
|
120
|
+
|
|
20
121
|
- **Templates de negócio**: `createECommerceIntegrations()`, `createSaaSIntegrations()`, `createCorporateIntegrations()`
|
|
21
122
|
- **Categorização inteligente**: `suggestCategoryForScript()` para sugestão automática de categorias
|
|
22
123
|
- **Configuração unificada**: Setup simplificado para múltiplas ferramentas com um comando
|
|
23
124
|
- **Padrões de mercado**: Templates baseados em necessidades reais do mercado brasileiro
|
|
24
125
|
|
|
25
126
|
### 🔧 **Melhorias no Sistema de Scripts**
|
|
127
|
+
|
|
26
128
|
- **Validação robusta**: `validateNecessaryClassification()` corrigida para evitar falsos positivos
|
|
27
129
|
- **Auto-configuração**: `autoConfigureCategories()` com detecção inteligente de categorias necessárias
|
|
28
130
|
- **Error handling**: Melhor tratamento de erros em carregamento de scripts
|
|
29
131
|
- **Performance**: Carregamento otimizado e lazy loading de integrações
|
|
30
132
|
|
|
31
133
|
### 🔍 **Descoberta Automática de Cookies (Experimental)**
|
|
134
|
+
|
|
32
135
|
- **discoverRuntimeCookies()**: Escaneamento de cookies em tempo real no navegador
|
|
33
136
|
- **detectConsentCookieName()**: Detecção automática do cookie de consentimento
|
|
34
137
|
- **categorizeDiscoveredCookies()**: Categorização inteligente usando padrões LGPD
|
|
@@ -36,17 +139,20 @@ O formato é baseado em [Keep a Changelog](https://keepachangelog.com/pt-BR/1.0.
|
|
|
36
139
|
- **SSR-safe**: Funciona corretamente em ambientes server-side rendering
|
|
37
140
|
|
|
38
141
|
### 🎨 **Design Tokens Expandidos**
|
|
142
|
+
|
|
39
143
|
- **200+ pontos de customização**: Expansão dramática do sistema de design tokens
|
|
40
144
|
- **Sistema responsivo**: Breakpoints, spacing responsivo, typography hierarchy
|
|
41
145
|
- **Acessibilidade nativa**: Contrast ratios, focus states, motion preferences
|
|
42
146
|
- **Tokens por componente**: Customização granular para cada elemento UI
|
|
43
147
|
|
|
44
148
|
### 📝 **Sistema Avançado de Textos**
|
|
149
|
+
|
|
45
150
|
- **Templates pré-configurados**: Ecommerce, SaaS, Governo com contextos específicos
|
|
46
151
|
- **Multilingual**: Português, inglês, espanhol com fallbacks inteligentes
|
|
47
152
|
- **Função resolveTexts**: Resolução automática de textos baseada em contexto
|
|
48
153
|
|
|
49
154
|
### 🧪 **Melhorias de Testes e Qualidade**
|
|
155
|
+
|
|
50
156
|
- **193 testes passando**: Cobertura substancialmente melhorada
|
|
51
157
|
- **19 novos testes**: Especificamente para `cookieRegistry` (antes 45.83% → 100% branches)
|
|
52
158
|
- **Test realism**: Testes adaptados ao comportamento real vs ideal
|
|
@@ -54,6 +160,7 @@ O formato é baseado em [Keep a Changelog](https://keepachangelog.com/pt-BR/1.0.
|
|
|
54
160
|
- **Lint compliance**: Configuração ESLint mais rigorosa e aderente
|
|
55
161
|
|
|
56
162
|
### 🔧 **Melhorias de API e Developer Experience**
|
|
163
|
+
|
|
57
164
|
- **Exports organizados**: Melhor estruturação das exportações públicas
|
|
58
165
|
- **TypeScript strict**: Tipagem mais rigorosa e descritiva
|
|
59
166
|
- **Documentação TSDoc**: Comentários expandidos com exemplos práticos
|
|
@@ -61,12 +168,14 @@ O formato é baseado em [Keep a Changelog](https://keepachangelog.com/pt-BR/1.0.
|
|
|
61
168
|
- **Performance**: Otimizações em carregamento e renderização
|
|
62
169
|
|
|
63
170
|
### 📚 **Exemplos e Migração**
|
|
171
|
+
|
|
64
172
|
- **MigrationDemo-v0.4.1.tsx**: Exemplo completo mostrando todas as novidades
|
|
65
173
|
- **Remoção**: TestV0.3.1.tsx removido (obsoleto)
|
|
66
174
|
- **Compatibilidade**: Guias de migração antes/depois
|
|
67
175
|
- **Best practices**: Demonstrações de uso avançado
|
|
68
176
|
|
|
69
177
|
### 🏗️ **Build e Infraestrutura**
|
|
178
|
+
|
|
70
179
|
- **Bundle otimizado**: ESM 34.36 KB, CJS 102.74 KB
|
|
71
180
|
- **Tree-shaking**: Configuração `sideEffects: false` otimizada
|
|
72
181
|
- **Docs geradas**: TypeDoc atualizado com novas funcionalidades
|
|
@@ -74,22 +183,25 @@ O formato é baseado em [Keep a Changelog](https://keepachangelog.com/pt-BR/1.0.
|
|
|
74
183
|
|
|
75
184
|
### ⚠️ **Breaking Changes**
|
|
76
185
|
|
|
77
|
-
#### 🔧 **`setPreference` Type Change**
|
|
186
|
+
#### 🔧 **`setPreference` Type Change**
|
|
187
|
+
|
|
78
188
|
- **Mudança**: `setPreference(cat: Category, value: boolean)` → `setPreference(cat: string, value: boolean)`
|
|
79
|
-
- **Motivo**: Suporte a categorias customizadas além das predefinidas
|
|
189
|
+
- **Motivo**: Suporte a categorias customizadas além das predefinidas
|
|
80
190
|
- **Impacto**: Código TypeScript com tipo `Category` explícito pode precisar ajustes
|
|
81
|
-
- **Migração**:
|
|
191
|
+
- **Migração**:
|
|
82
192
|
- ✅ **Nenhuma mudança necessária** se usando strings literais (`'analytics'`, `'marketing'`)
|
|
83
193
|
- ⚠️ **Ajuste necessário** apenas se estava usando explicitamente o tipo `Category`
|
|
84
194
|
- 📚 **Guia**: Use `string` para suportar categorias customizadas ou continue usando os valores padrão
|
|
85
195
|
|
|
86
196
|
#### 🔧 **`ScriptIntegration.category` Type Change**
|
|
197
|
+
|
|
87
198
|
- **Mudança**: `category: Category` → `category: string`
|
|
88
199
|
- **Motivo**: Suporte a categorias customizadas nas integrações de script
|
|
89
200
|
- **Impacto**: Integrações customizadas com tipo `Category` explícito
|
|
90
201
|
- **Migração**: Mesmas diretrizes do `setPreference` acima
|
|
91
202
|
|
|
92
203
|
### 🎯 **Categorias Suportadas**
|
|
204
|
+
|
|
93
205
|
- `necessary` (sempre ativo)
|
|
94
206
|
- `analytics` (Google Analytics, etc.)
|
|
95
207
|
- `marketing` (Facebook Pixel, Google Ads)
|
|
@@ -98,6 +210,7 @@ O formato é baseado em [Keep a Changelog](https://keepachangelog.com/pt-BR/1.0.
|
|
|
98
210
|
- `personalization` (Preferências, customização)
|
|
99
211
|
|
|
100
212
|
### 📈 **Estatísticas de Melhoria**
|
|
213
|
+
|
|
101
214
|
- **Design Tokens**: 4 → 200+ pontos de customização (+4900%)
|
|
102
215
|
- **Testes**: 174 → 193 testes (+11% cobertura)
|
|
103
216
|
- **Funcionalidades**: +15 novas funções exportadas
|
|
@@ -107,6 +220,7 @@ O formato é baseado em [Keep a Changelog](https://keepachangelog.com/pt-BR/1.0.
|
|
|
107
220
|
## [0.4.0] - 2025-09-09 — Custom categories
|
|
108
221
|
|
|
109
222
|
### Added
|
|
223
|
+
|
|
110
224
|
- Support for `customCategories` in `ConsentProvider.categories`.
|
|
111
225
|
- Included in preferences initialization and validation.
|
|
112
226
|
- Shown in the Preferences modal (with name/description).
|
|
@@ -115,6 +229,7 @@ O formato é baseado em [Keep a Changelog](https://keepachangelog.com/pt-BR/1.0.
|
|
|
115
229
|
- Storybook story: WithCustomCategories.
|
|
116
230
|
|
|
117
231
|
### Notes
|
|
232
|
+
|
|
118
233
|
- Non-breaking change; existing configurations continue to work.
|
|
119
234
|
|
|
120
235
|
## [0.3.7] - 2025-09-08 - Testes de UI e carregamento de scripts
|
|
@@ -656,3 +771,35 @@ A v0.2.1 introduz um **sistema inteligente de orientações** que guia desenvolv
|
|
|
656
771
|
- [ ] Base legal por categoria
|
|
657
772
|
- [ ] Relatórios de compliance
|
|
658
773
|
- [ ] Templates por setor
|
|
774
|
+
|
|
775
|
+
## [0.4.2] - 06/10/2025 — Quickstarts + SSR Guide + Validação (DEV)
|
|
776
|
+
|
|
777
|
+
### ✨ Quickstarts executáveis
|
|
778
|
+
|
|
779
|
+
- Next.js (App Router) e Vite com Consent Mode v2 integrado e bloqueio real de scripts (GTM/GA4 não carregam antes do consentimento).
|
|
780
|
+
- Seções no QUICKSTART.md com passos copy‑paste e validação do comportamento esperado.
|
|
781
|
+
|
|
782
|
+
### 🧱 Guia SSR/Next.js (App Router)
|
|
783
|
+
|
|
784
|
+
- 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.
|
|
785
|
+
- Ordem de provedores/estilos (Emotion/MUI) e z-index/portals documentados (overlay 1299, modais ≥ 1300).
|
|
786
|
+
|
|
787
|
+
### ✅ Validação de configuração do ConsentProvider (DEV)
|
|
788
|
+
|
|
789
|
+
- Validação com Zod em desenvolvimento (import dinâmico) e sanitização leve em produção.
|
|
790
|
+
- Mensagens amigáveis: alerta quando `categories` não é fornecida; remove `'necessary'` de `enabledCategories`; detecta duplicidades/valores inválidos; valida `customCategories`.
|
|
791
|
+
- Testes cobrindo casos inválidos e asserts de mensagens.
|
|
792
|
+
|
|
793
|
+
### 📚 Categorias — definição, uso e exemplos
|
|
794
|
+
|
|
795
|
+
- Fonte única de verdade: `ConsentProvider.categories`. UI, hooks e integrações leem a mesma definição.
|
|
796
|
+
- Esclarecimento: apenas “necessários” é obrigatório; demais categorias são opcionais conforme o negócio.
|
|
797
|
+
- Exemplos mínimo (somente necessários) e completo (analytics/marketing/functional).
|
|
798
|
+
|
|
799
|
+
### 🔧 Dependências
|
|
800
|
+
|
|
801
|
+
- Adicionado: `zod@^3.23.8` (usado somente em DEV via import dinâmico; não impacta o bundle de produção).
|
|
802
|
+
|
|
803
|
+
### 🧩 Sem breaking changes
|
|
804
|
+
|
|
805
|
+
- 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>
|
|
@@ -46,6 +52,19 @@ npm install react-lgpd-consent @mui/material @emotion/react @emotion/styled js-c
|
|
|
46
52
|
|
|
47
53
|
---
|
|
48
54
|
|
|
55
|
+
## ✨ Novidades v0.4.4
|
|
56
|
+
|
|
57
|
+
### 🔧 CI/CD e Publicação
|
|
58
|
+
- **Workflow de Publicação**: Corrigido bug que impedia publicação automática no npm quando tags eram criadas após merge para `main`
|
|
59
|
+
- **Codecov Integration**: Adicionado upload automático de coverage reports para melhor visualização de cobertura de testes
|
|
60
|
+
- **Badge de Coverage**: Agora atualizado em tempo real via Codecov
|
|
61
|
+
|
|
62
|
+
### 📊 Qualidade e Confiabilidade
|
|
63
|
+
- **Publicação Confiável**: Tags agora são publicadas corretamente quando commit está no histórico da `main`
|
|
64
|
+
- **Visibilidade de Cobertura**: Integração completa com Codecov para tracking de qualidade
|
|
65
|
+
|
|
66
|
+
---
|
|
67
|
+
|
|
49
68
|
## ✨ Novidades v0.4.1
|
|
50
69
|
|
|
51
70
|
### 🎨 Design Tokens Expandidos
|
|
@@ -113,6 +132,7 @@ Para mais detalhes sobre customização, hooks e funcionalidades, consulte os se
|
|
|
113
132
|
### 📋 Documentação Principal
|
|
114
133
|
|
|
115
134
|
- **[📚 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.
|
|
135
|
+
- 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
136
|
- Novo na v0.4.0: suporte a `customCategories` — veja a seção “Categorias customizadas (customCategories)” no Quickstart.
|
|
117
137
|
- 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
138
|
- 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,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
|
+
});
|