react-lgpd-consent 0.5.2 → 0.5.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/QUICKSTART.md CHANGED
@@ -16,9 +16,16 @@ yarn add react-lgpd-consent
16
16
  npm install @mui/material @mui/icons-material @emotion/react @emotion/styled
17
17
  ```
18
18
 
19
+ > ℹ️ **Modularização (v0.5.0+)**
20
+ >
21
+ > - `react-lgpd-consent` continua sendo o pacote principal publicado.
22
+ > - `@react-lgpd-consent/core` expõe apenas contextos, hooks e utilitários (sem UI).
23
+ > - `@react-lgpd-consent/mui` publica os componentes baseados em Material-UI (atualmente um proxy).
24
+ > - Use os novos subpaths (`react-lgpd-consent/core`, `react-lgpd-consent/mui`) conforme a necessidade.
25
+
19
26
  ## 🎯 Uso Básico (30 segundos)
20
27
 
21
- ````tsx
28
+ ```tsx
22
29
  import React from 'react'
23
30
  import { ConsentProvider } from 'react-lgpd-consent'
24
31
 
@@ -35,6 +42,7 @@ function App() {
35
42
  </main>
36
43
  </ConsentProvider>
37
44
  )
45
+ ```
38
46
 
39
47
  ## 🧭 Storybook — quick note
40
48
 
@@ -44,7 +52,7 @@ This repository ships an interactive Storybook playground used for manual testin
44
52
 
45
53
  ```bash
46
54
  npm run storybook
47
- ````
55
+ ```
48
56
 
49
57
  - Build static Storybook (for publishing to GitHub Pages):
50
58
 
@@ -56,11 +64,6 @@ Notes:
56
64
 
57
65
  - The Storybook preview (`.storybook/preview.tsx`) applies a clean environment between stories (removes consent cookie and performs defensive DOM cleanup). Check that file when creating stories that rely on a clean initial state.
58
66
 
59
- }
60
-
61
- export default App
62
-
63
- ````
64
67
 
65
68
  ## ⚡ Quickstarts: Next.js (App Router) e Vite
66
69
 
@@ -395,8 +398,8 @@ function MyComponent() {
395
398
 
396
399
  ## 📋 Tabela Completa de Props do ConsentProvider
397
400
 
398
- | Prop | Tipo | Obrigatória | Padrão | Descrição |
399
- | ------------------------------------ | ----------------------------------------------------------- | ----------- | ------------------- | ---------------------------------------------- |
401
+ | Prop | Tipo | Obrigatória | Padrão | Descrição |
402
+ | ----------------- | ------------------------------------------------ | ----------- | -------------- | --------------------------------------- |
400
403
  | `categories` | `ProjectCategoriesConfig` | ✅ **Sim** | - | Define as categorias de cookies do projeto |
401
404
  | `texts` | `Partial<ConsentTexts>` | ❌ Não | Textos padrão PT-BR | Customiza textos da interface |
402
405
  | `theme` | `any` | ❌ Não | Tema padrão | Tema Material-UI para os componentes |
@@ -415,7 +418,89 @@ function MyComponent() {
415
418
  | `preferencesModalProps` | `object` | ❌ Não | `{}` | Props adicionais para o modal |
416
419
  | `floatingPreferencesButtonProps` | `object` | ❌ Não | `{}` | Props adicionais para o botão flutuante |
417
420
  | `initialState` | `ConsentState` | ❌ Não | - | Estado inicial para hidratação SSR |
418
- | `cookie` | `Partial<ConsentCookieOptions>` | ❌ Não | Opções padrão | Configurações do cookie de consentimento |
421
+ | `cookie` | `Partial<ConsentCookieOptions>` | ❌ Não | Opções padrão | Configurações do cookie (override fino de `name`, `domain`, `sameSite` etc.) |
422
+ | `storage` | `ConsentStorageConfig` | ❌ Não | `{ namespace: 'lgpd-consent', version: '1' }` | Namespace, versão e domínio compartilhado da chave de consentimento |
423
+ | `onConsentVersionChange` | `(context: ConsentVersionChangeContext) => void` | ❌ Não | Reset automático | Hook disparado após bump da chave; use para limpar caches adicionais |
424
+
425
+ ## 🔄 Versionamento de Consentimento (0.5.x)
426
+
427
+ - **Resumo da solicitação**: namespace + versão para a chave de consentimento e estratégia de migração entre releases, garantindo compartilhamento entre subdomínios.
428
+ - **Caso de uso — problema que resolve**: quando o escopo de dados muda (novas categorias, integrações etc.), usuários precisam reafirmar consentimento. Sem um identificador de versão, o estado antigo permanece ativo e quebra conformidade.
429
+
430
+ ### Solução proposta
431
+ - `storage.namespace` e `storage.version` geram automaticamente o nome do cookie via `buildConsentStorageKey`, mantendo o schema `namespace__v<versão>` (`lgpd-consent__v1` por padrão).
432
+ - `storage.domain` centraliza o domínio compartilhado (ex.: `.gov.br`) para que um único banner sirva múltiplos subdomínios.
433
+ - `onConsentVersionChange` é chamado sempre que a chave muda. O reset do estado é automático, mas o hook permite limpar caches customizados (ex.: localStorage, indexedDB) antes de liberar a nova experiência.
434
+ - Guia de migração: documente no seu changelog interno quando e por que o valor de `storage.version` mudou. O bump NÃO é breaking change porque a API pública permanece compatível—apenas força o fluxo de re-consent.
435
+ - Breaking change? **Não** — quem não configurar `storage` continua usando `lgpd-consent__v1`; ao aumentar a versão apenas ocorre re-consentimento.
436
+
437
+ ### Critérios de aceitação
438
+ - Trocar `storage.version` força o fluxo completo: cookie antigo removido, `ConsentProvider` volta ao estado sem consentimento e o usuário vê o banner novamente.
439
+ - Subdomínios compartilham o mesmo consentimento quando `storage.domain` usa um domínio com ponto (`.example.com`).
440
+ - `onConsentVersionChange` entrega `previousKey`, `nextKey` e `resetConsent` para coordenar invalidação de caches externos.
441
+
442
+ ## 🔒 Cookies necessários sempre ativos
443
+
444
+ - **Resumo da solicitação**: implementar a política de “necessários sempre ativos” tanto na UI quanto na persistência.
445
+ - **Caso de uso — problema resolvido**: atende ao requisito LGPD/ANPD de que cookies estritamente necessários não podem ser desativados; evita confusão na interface e garante consistência nos hooks.
446
+
447
+ ### Como a biblioteca reforça a regra
448
+ - A categoria `necessary` é adicionada automaticamente pelo `ConsentProvider` e sempre persistida como `true`.
449
+ - `setPreference('necessary', false)` e `setPreferences({ necessary: false, ... })` são ignorados com logs de aviso — o estado permanece com `necessary=true`.
450
+ - O `PreferencesModal` padrão exibe a categoria com switch desabilitado e o texto `Cookies necessários (sempre ativos)`.
451
+ - `writeConsentCookie` garante `necessary=true` mesmo que o estado enviado esteja corrompido.
452
+ - Hooks (`useConsent`, `useCategoryStatus`) e integrações (`ConsentScriptLoader`, dataLayer) sempre recebem `necessary=true`.
453
+
454
+ ### Exemplo (apenas cookies necessários)
455
+
456
+ ```tsx
457
+ import { ConsentProvider } from '@react-lgpd-consent/core'
458
+
459
+ export function MinimalBoundary({ children }: { children: React.ReactNode }) {
460
+ return <ConsentProvider categories={{ enabledCategories: [] }}>{children}</ConsentProvider>
461
+ }
462
+ ```
463
+
464
+ ### Critérios de aceitação
465
+ - UI, hooks, persistência e dataLayer mantêm `necessary=true` em todos os caminhos.
466
+ - Testes automatizados cobrem tentativas de toggle/programmatic override e serialização.
467
+ - Breaking change? **Não** — o comportamento já era esperado; agora é reforçado pelo runtime com avisos para cenários indevidos.
468
+
469
+ ### Exemplo completo (namespace + versão + subdomínio)
470
+
471
+ ```tsx
472
+ import { buildConsentStorageKey, ConsentProvider } from 'react-lgpd-consent'
473
+
474
+ function ComplianceWrapper({ children }: { children: React.ReactNode }) {
475
+ return (
476
+ <ConsentProvider
477
+ categories={{ enabledCategories: ['analytics', 'marketing'] }}
478
+ storage={{
479
+ namespace: 'portal.gov.br',
480
+ version: '2025-Q4',
481
+ domain: '.gov.br',
482
+ }}
483
+ cookie={{
484
+ // Opcional: sobrescreva o nome explicitamente (útil para auditoria legada)
485
+ name: buildConsentStorageKey({ namespace: 'portal.gov.br', version: '2025-Q4' }),
486
+ }}
487
+ onConsentVersionChange={({ previousKey, nextKey, resetConsent }) => {
488
+ console.info('[consent] versão atualizada', { previousKey, nextKey })
489
+ window.dataLayer?.push({ event: 'consent_version_bumped', previousKey, nextKey })
490
+ localStorage.removeItem('marketing-optins')
491
+ resetConsent()
492
+ }}
493
+ >
494
+ {children}
495
+ </ConsentProvider>
496
+ )
497
+ }
498
+ ```
499
+
500
+ ### Alternativas consideradas
501
+ - **Invalidar sempre** (reset em toda visita) prejudica a UX e reduz taxas de aceitação.
502
+ - **Nunca invalidar** mantém consentimentos fora de escopo e compromete a conformidade.
503
+ - A solução de namespace + versão expõe explicitamente quando o reconsentimento é necessário.
419
504
 
420
505
  ## 🎨 Componentes Customizados com TypeScript
421
506
 
@@ -481,7 +566,7 @@ A biblioteca `react-lgpd-consent` não injeta um `ThemeProvider` global por cont
481
566
 
482
567
  ```tsx
483
568
  import { ConsentProvider, createDefaultConsentTheme } from 'react-lgpd-consent'
484
- ;<ConsentProvider
569
+ <ConsentProvider
485
570
  theme={createDefaultConsentTheme()}
486
571
  categories={{ enabledCategories: ['analytics'] }}
487
572
  >
@@ -489,6 +574,7 @@ import { ConsentProvider, createDefaultConsentTheme } from 'react-lgpd-consent'
489
574
  </ConsentProvider>
490
575
  ```
491
576
 
577
+
492
578
  Isso evita alterações indesejadas no contexto do MUI do seu app e problemas de SSR.
493
579
 
494
580
  ```tsx