-
Google Consent Mode v2 Automático
- GA4 e GTM agora implementam Consent Mode v2 sem configuração manual
bootstrap: Seta consent padrão antes do carregamentoonConsentUpdate: Atualiza consent quando preferências mudam
-
Sistema de Fila de Scripts com Prioridade
- Nova API
registerScript()para registro programático - Scripts executam em ordem: necessary → categoria → prioridade → timestamp
- Interface
RegisteredScriptcompriority,allowReload,onConsentUpdate
- Nova API
-
Cookie Options Modernizadas
- NOVO:
maxAgeem segundos (padrão moderno) - DEPRECATED:
maxAgeDays(mantido por compatibilidade) - NOVO: Suporte a
sameSite: 'None'para contextos cross-site - Detecção automática de HTTPS para
secure: true
- NOVO:
-
Entrypoint UI-only (
@react-lgpd-consent/mui/ui)- Exporta apenas a camada MUI, sem re-exportar o core
- Reduz ambiguidade de nomes (
ConsentProviderheadless vs. MUI) e melhora tree-shaking
Cookie Options (Opcional, backward compatible):
<ConsentProvider
cookie={{
name: 'myConsent',
- maxAgeDays: 365,
+ maxAge: 365 * 24 * 60 * 60, // 365 dias em segundos
sameSite: 'Lax',
secure: true // Detectado automaticamente em HTTPS
}}
>Google Consent Mode v2 (Automático, nenhuma mudança necessária!):
// Antes v0.7.1: Configuração manual complexa
function GtagConsentBootstrap() {
React.useEffect(() => {
gtag('consent', 'default', { analytics_storage: 'denied' })
}, [])
}
// Depois v0.7.1: Automático!
const integrations = [
createGoogleAnalyticsIntegration({ measurementId: 'G-XXX' })
]
<ConsentScriptLoader integrations={integrations} />
// ✅ Consent Mode v2 implementado automaticamenteRegistro Programático de Scripts (Nova feature):
import { registerScript } from 'react-lgpd-consent'
// Registre scripts fora do JSX com prioridade e callbacks
const cleanup = registerScript({
id: 'custom-script',
category: 'analytics',
priority: 10, // Maior = executa primeiro
execute: async () => {
await loadMyScript()
},
onConsentUpdate: ({ consented, preferences }) => {
if (preferences.analytics) {
updateMyScriptConsent('granted')
}
}
})
// Cleanup quando componente desmontar
React.useEffect(() => cleanup, [])UI-only (reduzir bundle e evitar ambiguidade):
-import { ConsentProvider, CookieBanner } from '@react-lgpd-consent/mui'
+import { ConsentProvider, CookieBanner } from '@react-lgpd-consent/mui/ui'Precisa da lógica headless? Importe direto do @react-lgpd-consent/core ou use headless.ConsentProvider do entrypoint principal.
Nenhum! Todas as mudanças são backward compatible.
maxAgeDayscontinua funcionando (mas deprecated)- Comportamento padrão preservado
- APIs existentes mantidas
A versão 0.5.0 introduz uma arquitetura modular que permite escolher entre diferentes níveis de dependência:
@react-lgpd-consent/core: Lógica headless de consentimento (sem UI, sem Material-UI)@react-lgpd-consent/mui: Componentes UI completos usando Material-UIreact-lgpd-consent: Pacote agregador (mantido para compatibilidade, inclui core + mui)
- Tree-shaking eficiente: Instale apenas o que você precisa
- Flexibilidade de UI: Use core com sua própria biblioteca de componentes
- Redução de bundle: Core tem ~86 KB vs pacote completo ~104 KB
- Independência de MUI: Core não depende do Material-UI
| Pacote | Quando Usar | Tamanho Bundle | Dependências |
|---|---|---|---|
@react-lgpd-consent/core |
Criar UI customizada ou usar outra biblioteca de componentes | ~86 KB | React, js-cookie, zod |
@react-lgpd-consent/mui |
Usar componentes prontos com Material-UI | ~104 KB (core + mui) | Core + @mui/material |
react-lgpd-consent |
Manter compatibilidade ou preferir pacote único | ~104 KB | Core + MUI |
Antes (v0.4.x):
npm install react-lgpd-consent @mui/material @emotion/react @emotion/styledDepois (v0.5.0 - Opção A: Pacote agregador):
# Mantém compatibilidade total, sem mudanças no código
npm install react-lgpd-consent @mui/material @emotion/react @emotion/styledDepois (v0.5.0 - Opção B: Pacote MUI direto - RECOMENDADO):
# Mesma funcionalidade, pacote mais explícito
npm install @react-lgpd-consent/mui @mui/material @emotion/react @emotion/styledMudanças no código:
-import { ConsentProvider, CookieBanner } from 'react-lgpd-consent'
+import { ConsentProvider, CookieBanner, FloatingPreferencesButton } from '@react-lgpd-consent/mui'
function App() {
return (
<ConsentProvider categories={{ enabledCategories: ['analytics'] }}>
<CookieBanner />
- <PreferencesModal />
<FloatingPreferencesButton />
+ {/* O PreferencesModal é injetado automaticamente! */}
</ConsentProvider>
)
}✨ Novidade v0.5.0: O
ConsentProviderdo pacote MUI automaticamente renderiza oPreferencesModal. Você não precisa incluí-lo manualmente!
Customizando o modal:
import { ConsentProvider, PreferencesModal } from '@react-lgpd-consent/mui'
<ConsentProvider
categories={{ enabledCategories: ['analytics'] }}
PreferencesModalComponent={(props) => (
<PreferencesModal {...props} hideBranding={true} />
)}
>
<YourApp />
</ConsentProvider>Antes (v0.4.x):
# Instalava Material-UI mesmo sem usar componentes UI
npm install react-lgpd-consent @mui/material @emotion/react @emotion/styledDepois (v0.5.0 - Core apenas):
# Zero dependências de UI!
npm install @react-lgpd-consent/coreExemplo de uso:
import { ConsentProvider, useConsent } from '@react-lgpd-consent/core'
// Crie seus próprios componentes UI
function CustomBanner() {
const { acceptAll, declineAll } = useConsent()
return (
<div className="my-custom-banner">
<button onClick={acceptAll}>Aceitar</button>
<button onClick={declineAll}>Recusar</button>
</div>
)
}
function App() {
return (
<ConsentProvider categories={{ enabledCategories: ['analytics'] }}>
<CustomBanner />
{/* Seu app */}
</ConsentProvider>
)
}Alternativa: Usar ConsentProviderHeadless do MUI:
import { ConsentProviderHeadless, useConsent } from '@react-lgpd-consent/mui'
function App() {
return (
<ConsentProviderHeadless categories={{ enabledCategories: ['analytics'] }}>
<CustomBanner />
</ConsentProviderHeadless>
)
}v0.5.0 - Separação clara client/server:
// app/providers.tsx (Client Component)
'use client'
import { ConsentProvider } from '@react-lgpd-consent/mui'
export function Providers({ children }: { children: React.ReactNode }) {
return (
<ConsentProvider categories={{ enabledCategories: ['analytics'] }}>
{children}
</ConsentProvider>
)
}
// app/layout.tsx (Server Component)
import { Providers } from './providers'
export default function RootLayout({ children }) {
return (
<html>
<body>
<Providers>{children}</Providers>
</body>
</html>
)
}Antes (v0.4.x):
import { createTheme } from '@mui/material/styles'
<ConsentProvider
theme={createTheme({ palette: { mode: 'dark' } })}
categories={{ enabledCategories: ['analytics'] }}
>
{/* ... */}
</ConsentProvider>Depois (v0.5.0):
import { ThemeProvider, createTheme } from '@mui/material/styles'
import { ConsentProvider } from '@react-lgpd-consent/mui'
<ThemeProvider theme={createTheme({ palette: { mode: 'dark' } })}>
<ConsentProvider categories={{ enabledCategories: ['analytics'] }}>
{/* ... */}
</ConsentProvider>
</ThemeProvider>Razão: Separação de responsabilidades - tema do MUI deve ser gerenciado pelo MUI.
Antes (v0.4.x):
react-lgpd-consent (tudo junto)
Depois (v0.5.0):
@react-lgpd-consent/core (lógica)
@react-lgpd-consent/mui (UI)
react-lgpd-consent (agregador, mantido para compatibilidade)
- ✅ Todas as APIs públicas do
useConsent - ✅ Props de
ConsentProvider(excetotheme) - ✅ Componentes
CookieBanner,PreferencesModal,FloatingPreferencesButton - ✅ Sistema de textos e templates (
TEXT_TEMPLATES,resolveTexts) - ✅ Sistema de design tokens (
designTokens) - ✅ Integrações (
createGoogleAnalyticsIntegration,createGoogleTagManagerIntegration, etc.) - ✅ SSR/NextJS support
- ✅ TypeScript types
Pergunta-chave: Você usa os componentes UI da biblioteca?
-
✅ Sim, uso
CookieBanner,PreferencesModal, etc.- → Migre para
@react-lgpd-consent/muiOU mantenhareact-lgpd-consent
- → Migre para
-
❌ Não, criei meus próprios componentes
- → Migre para
@react-lgpd-consent/core(reduz bundle em ~18 KB)
- → Migre para
# Mantém tudo como está
npm install react-lgpd-consent@0.5.0✅ Nenhuma mudança de código necessária
✅ Funciona imediatamente
# Fase 1: Instale o novo pacote ao lado do antigo
npm install @react-lgpd-consent/mui
# Fase 2: Atualize imports gradualmente
# (pode misturar imports durante transição)
# Fase 3: Remova o pacote antigo quando estiver pronto
npm uninstall react-lgpd-consent# Para quem não usa componentes UI
npm uninstall react-lgpd-consent @mui/material
npm install @react-lgpd-consent/coreBuscar e substituir:
-import { ... } from 'react-lgpd-consent'
+import { ... } from '@react-lgpd-consent/mui' // Se usa UI
+import { ... } from '@react-lgpd-consent/core' // Se não usa UI+import { ThemeProvider } from '@mui/material/styles'
-<ConsentProvider theme={myTheme}>
+<ThemeProvider theme={myTheme}>
+ <ConsentProvider>
{/* ... */}
+ </ConsentProvider>
+</ThemeProvider>
-</ConsentProvider># Executar type-check
npm run type-check
# Executar testes
npm test
# Executar build
npm run buildCausa: Tentando importar do core mas instalou react-lgpd-consent.
Solução:
npm install @react-lgpd-consent/core
# OU
npm install @react-lgpd-consent/muiCausa: Usando prop theme removida na v0.5.0.
Solução: Use ThemeProvider do Material-UI:
import { ThemeProvider } from '@mui/material/styles'
<ThemeProvider theme={myTheme}>
<ConsentProvider {...props}>
{children}
</ConsentProvider>
</ThemeProvider>Causa: Instalou react-lgpd-consent mas não usa componentes UI.
Solução: Migre para @react-lgpd-consent/core:
npm uninstall react-lgpd-consent
npm install @react-lgpd-consent/coreCausa: Paths do TypeScript podem precisar de ajuste.
Solução: Adicione em tsconfig.json:
{
"compilerOptions": {
"paths": {
"@react-lgpd-consent/core": ["./node_modules/@react-lgpd-consent/core"],
"@react-lgpd-consent/mui": ["./node_modules/@react-lgpd-consent/mui"]
}
}
}| Versão | Pacote | ESM | CJS | DTS |
|---|---|---|---|---|
| 0.4.x | react-lgpd-consent |
~105 KB | ~110 KB | ~130 KB |
| 0.5.0 | @react-lgpd-consent/core |
86 KB | 89 KB | 126 KB |
| 0.5.0 | @react-lgpd-consent/mui |
18 KB* | 21 KB* | 12 KB* |
| 0.5.0 | react-lgpd-consent |
104 KB | 110 KB | 138 KB |
* MUI pacote importa core, bundle final = core + mui (~104 KB)
Antes:
import { ConsentProvider, CookieBanner } from 'react-lgpd-consent'
import { createTheme, ThemeProvider } from '@mui/material/styles'
const theme = createTheme({ palette: { mode: 'dark' } })
function App() {
return (
<ConsentProvider
theme={theme}
categories={{ enabledCategories: ['analytics', 'marketing'] }}
>
<CookieBanner />
{/* app */}
</ConsentProvider>
)
}Depois:
import { ConsentProvider, CookieBanner } from '@react-lgpd-consent/mui'
import { createTheme, ThemeProvider } from '@mui/material/styles'
const theme = createTheme({ palette: { mode: 'dark' } })
function App() {
return (
<ThemeProvider theme={theme}>
<ConsentProvider
categories={{ enabledCategories: ['analytics', 'marketing'] }}
>
<CookieBanner />
{/* app */}
</ConsentProvider>
</ThemeProvider>
)
}Antes:
import { ConsentProvider, useConsent } from 'react-lgpd-consent'
// Instalava @mui/material mesmo sem usarDepois:
import { ConsentProvider, useConsent } from '@react-lgpd-consent/core'
// Sem dependências de @mui/material!
function MyCustomBanner() {
const { acceptAll, declineAll, preferences } = useConsent()
return (
<div className="my-banner">
<p>Usamos cookies para analytics</p>
<button onClick={acceptAll}>Aceitar</button>
<button onClick={declineAll}>Recusar</button>
</div>
)
}Instalação:
npm install @react-lgpd-consent/coreUso:
// src/main.tsx
import { ConsentProvider } from '@react-lgpd-consent/core'
import { MyCustomBanner } from './components/MyCustomBanner'
function App() {
return (
<ConsentProvider categories={{ enabledCategories: ['analytics', 'marketing'] }}>
<MyCustomBanner />
<YourApp />
</ConsentProvider>
)
}
// src/components/MyCustomBanner.tsx
import { useConsent } from '@react-lgpd-consent/core'
export function MyCustomBanner() {
const { acceptAll, declineAll, consented } = useConsent()
if (consented) return null
return (
<div className="fixed bottom-0 left-0 right-0 bg-gray-900 text-white p-4 shadow-lg">
<div className="container mx-auto flex items-center justify-between">
<p className="text-sm">
🍪 Usamos cookies para melhorar sua experiência
</p>
<div className="flex gap-2">
<button
onClick={declineAll}
className="px-4 py-2 bg-gray-700 hover:bg-gray-600 rounded"
>
Recusar
</button>
<button
onClick={acceptAll}
className="px-4 py-2 bg-blue-600 hover:bg-blue-500 rounded"
>
Aceitar
</button>
</div>
</div>
</div>
)
}Instalação:
npm install @react-lgpd-consent/mui @mui/material @emotion/react @emotion/styledEstrutura:
// app/providers.tsx
'use client'
import { ConsentProvider } from '@react-lgpd-consent/mui'
import { ThemeProvider, createTheme } from '@mui/material/styles'
import CssBaseline from '@mui/material/CssBaseline'
const theme = createTheme({
palette: {
mode: 'light',
primary: { main: '#1976d2' },
},
})
export function Providers({ children }: { children: React.ReactNode }) {
return (
<ThemeProvider theme={theme}>
<CssBaseline />
<ConsentProvider
categories={{
enabledCategories: ['analytics', 'marketing', 'functional'],
}}
>
{children}
</ConsentProvider>
</ThemeProvider>
)
}
// app/layout.tsx
import { Providers } from './providers'
export default function RootLayout({ children }: { children: React.ReactNode }) {
return (
<html lang="pt-BR">
<body>
<Providers>{children}</Providers>
</body>
</html>
)
}
// app/page.tsx
export default function Home() {
return <main>Seu conteúdo</main>
}Instalação:
npm install @react-lgpd-consent/core @chakra-ui/react @emotion/react @emotion/styledUso:
// src/index.tsx
import { ChakraProvider } from '@chakra-ui/react'
import { ConsentProvider } from '@react-lgpd-consent/core'
import { CustomConsentBanner } from './components/CustomConsentBanner'
function App() {
return (
<ChakraProvider>
<ConsentProvider categories={{ enabledCategories: ['analytics'] }}>
<CustomConsentBanner />
<YourApp />
</ConsentProvider>
</ChakraProvider>
)
}
// src/components/CustomConsentBanner.tsx
import { Box, Button, Text, Flex } from '@chakra-ui/react'
import { useConsent } from '@react-lgpd-consent/core'
export function CustomConsentBanner() {
const { acceptAll, declineAll, consented } = useConsent()
if (consented) return null
return (
<Box
position="fixed"
bottom={0}
left={0}
right={0}
bg="gray.800"
color="white"
p={4}
shadow="lg"
>
<Flex maxW="container.xl" mx="auto" align="center" justify="space-between">
<Text fontSize="sm">
🍪 Usamos cookies para análise e personalização
</Text>
<Flex gap={2}>
<Button size="sm" variant="ghost" onClick={declineAll}>
Recusar
</Button>
<Button size="sm" colorScheme="blue" onClick={acceptAll}>
Aceitar
</Button>
</Flex>
</Flex>
</Box>
)
}Instalação:
npm install @react-lgpd-consent/mui @mui/material @emotion/react @emotion/styledUso:
// app/root.tsx
import { Links, LiveReload, Meta, Outlet, Scripts, ScrollRestoration } from '@remix-run/react'
import { ConsentProvider, CookieBanner } from '@react-lgpd-consent/mui'
import { ThemeProvider, createTheme } from '@mui/material/styles'
const theme = createTheme()
export default function App() {
return (
<html lang="pt-BR">
<head>
<Meta />
<Links />
</head>
<body>
<ThemeProvider theme={theme}>
<ConsentProvider categories={{ enabledCategories: ['analytics', 'marketing'] }}>
<CookieBanner />
<Outlet />
</ConsentProvider>
</ThemeProvider>
<ScrollRestoration />
<Scripts />
<LiveReload />
</body>
</html>
)
}import { ConsentProvider, createGoogleAnalyticsIntegration } from '@react-lgpd-consent/core'
const ga4Integration = createGoogleAnalyticsIntegration('G-XXXXXXXXXX')
function App() {
return (
<ConsentProvider
categories={{ enabledCategories: ['analytics'] }}
integrations={[ga4Integration]}
>
<YourApp />
</ConsentProvider>
)
}import { ConsentProvider, createGoogleTagManagerIntegration } from '@react-lgpd-consent/core'
const gtmIntegration = createGoogleTagManagerIntegration('GTM-XXXXXXX')
function App() {
return (
<ConsentProvider
categories={{ enabledCategories: ['analytics', 'marketing'] }}
integrations={[gtmIntegration]}
>
<YourApp />
</ConsentProvider>
)
}import {
ConsentProvider,
createGoogleAnalyticsIntegration,
createGoogleTagManagerIntegration,
createUserWayIntegration,
} from '@react-lgpd-consent/core'
const integrations = [
createGoogleAnalyticsIntegration('G-XXXXXXXXXX'),
createGoogleTagManagerIntegration('GTM-XXXXXXX'),
createUserWayIntegration('your-userway-account-id'),
]
function App() {
return (
<ConsentProvider
categories={{
enabledCategories: ['necessary', 'analytics', 'marketing', 'functional'],
}}
integrations={integrations}
>
<YourApp />
</ConsentProvider>
)
}- README Principal - Documentação geral
- API Reference - API completa
- Exemplos - Exemplos práticos
- CHANGELOG - Histórico de mudanças
Não. O pacote react-lgpd-consent continua funcionando e será mantido. Migre quando fizer sentido para seu projeto.
Sim, temporariamente. Durante a migração, você pode importar de react-lgpd-consent e @react-lgpd-consent/mui simultaneamente. Mas a longo prazo, escolha um.
Não. A v0.5.0 é refatoração de arquitetura sem novas funcionalidades. O foco é modularidade e tree-shaking.
- Use
@react-lgpd-consent/muise você quer os componentes prontos - Use
@react-lgpd-consent/corese você vai criar sua própria UI
Continua existindo como pacote agregador (importa core + mui). Mantido para compatibilidade, mas recomendamos usar os pacotes específicos.
Após migrar:
- ✅ Execute
npm run type-checkenpm test - ✅ Verifique o tamanho do bundle (
npm run build) - ✅ Teste em staging antes de produção
- ✅ Atualize documentação interna do projeto
- ✅ Considere contribuir com feedback ou issues no GitHub
Precisa de ajuda? Abra uma issue no GitHub ou consulte a documentação completa.