react-lgpd-consent 0.3.3 → 0.3.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/README.md CHANGED
@@ -4,42 +4,35 @@
4
4
 
5
5
  <div>
6
6
  <a href="https://www.npmjs.com/package/react-lgpd-consent"><img src="https://img.shields.io/npm/v/react-lgpd-consent?style=for-the-badge&logo=npm&color=cb3837&logoColor=white" alt="NPM Version"></a>
7
- <a href="https://www.npmjs.com/package/react-lgpd-consent"><img src="https://img.shields.io/npm/dm/react-lgpd-consent?style=for-the-badge&logo=npm&color=ff6b35&logoColor=white" alt="Downloads"></a>
8
- <a href="https://github.com/lucianoedipo/react-lgpd-consent/blob/main/LICENSE"><img src="https://img.shields.io/npm/l/react-lgpd-consent?style=for-the-badge&color=green&logoColor=white" alt="License"></a>
7
+ <a href="https://www.npmjs.com/package/react-lgpd-consent"><img src="https://img.shields.io/npm/dm/react-lgpd-consent?style=for-the-badge&logo=npm&color=ff6b35&logoColor=white" alt="Downloads"></a>
8
+ <a href="https://github.com/lucianoedipo/react-lgpd-consent/blob/main/LICENSE"><img src="https://img.shields.io/npm/l/react-lgpd-consent?style=for-the-badge&color=green&logoColor=white" alt="License"></a>
9
+ <a href="https://lucianoedipo.github.io/react-lgpd-consent/storybook/"><img src="https://img.shields.io/badge/Storybook-Playground-ff4785?style=for-the-badge&logo=storybook&logoColor=white" alt="Storybook"></a>
9
10
  </div>
10
-
11
+
11
12
  <div>
12
13
  <a href="https://www.typescriptlang.org/"><img src="https://img.shields.io/badge/TypeScript-Ready-3178c6?style=for-the-badge&logo=typescript&logoColor=white" alt="TypeScript Ready"></a>
13
14
  <a href="https://reactjs.org/"><img src="https://img.shields.io/badge/React-18+-61dafb?style=for-the-badge&logo=react&logoColor=white" alt="React 18+"></a>
14
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>
15
16
  </div>
16
17
 
17
- <br>
18
+ <br />
18
19
 
19
20
  <p>
20
21
  <a href="#-instalação"><strong>Instalação</strong></a> •
21
22
  <a href="#-uso-básico"><strong>Uso Básico</strong></a> •
22
- <a href="#-documentação-completa"><strong>Documentação</strong></a> •
23
+ <a href="./QUICKSTART.md"><strong>📚 Guia de Início Rápido</strong></a> •
24
+ <a href="#-documentação-completa"><strong>Documentação</strong></a> •
25
+ <a href="./README.en.md">🇺🇸 🇬🇧 English</a> •
23
26
  <a href="#-como-contribuir"><strong>Contribuir</strong></a>
24
27
  </p>
25
- </div>
26
-
27
- ---
28
-
29
- ## 🎯 Por que usar `react-lgpd-consent`?
30
-
31
- Esta biblioteca oferece uma solução robusta e flexível para gerenciar o consentimento de cookies em aplicações React, com foco total na **Lei Geral de Proteção de Dados (LGPD)** do Brasil.
32
28
 
33
- ### Principais Funcionalidades
29
+ <!-- Quickstart callout (mantido) -->
30
+ <p align="center">
31
+ <a href="./QUICKSTART.md"><img src="https://img.shields.io/badge/Quickstart-Iniciar%20R%C3%A1pido-blue?style=for-the-badge&logo=book" alt="Quickstart"></a>
32
+ </p>
34
33
 
35
- | Funcionalidade | Descrição |
36
- | -------------------------------- | ----------------------------------------------------------------------------------------------------- |
37
- | 🇧🇷 **Foco na LGPD** | Implementação baseada nas diretrizes da ANPD, com textos e categorias alinhados à lei brasileira. |
38
- | 🎨 **UI Automática e Customizável** | Componentes de UI (Banner e Modal) prontos para uso, baseados em Material-UI, e totalmente substituíveis. |
39
- | ⚙️ **Configuração Consciente** | A prop `categories` força a declaração explícita dos cookies utilizados, seguindo o princípio da minimização. |
40
- | 🧠 **Guia para Desenvolvedores** | Sistema que exibe avisos e sugestões no console (em ambiente de dev) para garantir a correta implementação. |
41
- | 🚀 **Integrações Nativas** | Carregamento automático de scripts como Google Analytics e GTM, condicionado ao consentimento do usuário. |
42
- | 🔒 **Auditoria e Transparência** | O cookie de consentimento armazena metadados como data, origem e versão para fins de auditoria. |
34
+ <p align="center"><strong>Comece por aqui:</strong> siga o <a href="./QUICKSTART.md">Guia de Início Rápido (QUICKSTART.md)</a> para um tutorial passo-a-passo, exemplos TypeScript, tabela de props e integração com MUI — recomendado para usuários novos.</p>
35
+ </div>
43
36
 
44
37
  ---
45
38
 
@@ -49,98 +42,47 @@ Esta biblioteca oferece uma solução robusta e flexível para gerenciar o conse
49
42
  npm install react-lgpd-consent @mui/material @emotion/react @emotion/styled js-cookie
50
43
  ```
51
44
 
52
- **Dependências Peer:**
53
-
54
- A biblioteca requer `react`, `react-dom`, `@mui/material` e `js-cookie` como dependências peer.
45
+ **Dependências peer:** `react`, `react-dom`, `@mui/material` e `js-cookie`.
55
46
 
56
47
  ---
57
48
 
58
49
  ## 📖 Uso Básico
59
50
 
60
- Envolva sua aplicação com o `ConsentProvider` e configure as categorias de cookies que você utiliza.
51
+ Envolva sua aplicação com o `ConsentProvider` (exemplo mínimo):
61
52
 
62
53
  ```tsx
63
- // Em seu arquivo principal (ex: App.tsx)
64
- import { ConsentProvider } from 'react-lgpd-consent';
54
+ import { ConsentProvider } from 'react-lgpd-consent'
65
55
 
66
- function App() {
56
+ export default function App() {
67
57
  return (
68
- <ConsentProvider
69
- categories={{
70
- // É obrigatório especificar as categorias que seu site usa.
71
- // A categoria 'necessary' é sempre incluída.
72
- enabledCategories: ['analytics', 'marketing'],
73
- }}
74
- >
75
- {/* O banner e o botão de preferências aparecerão automaticamente */}
76
- <SuaAplicacao />
58
+ <ConsentProvider categories={{ enabledCategories: ['analytics'] }}>
59
+ <YourApp />
77
60
  </ConsentProvider>
78
- );
61
+ )
79
62
  }
80
63
  ```
81
64
 
82
- ### Exemplo com Integração e Textos Customizados
83
-
84
- ```tsx
85
- import {
86
- ConsentProvider,
87
- ConsentScriptLoader,
88
- createGoogleAnalyticsIntegration,
89
- } from 'react-lgpd-consent';
90
-
91
- // 1. Crie as integrações que você precisa
92
- const integrations = [
93
- createGoogleAnalyticsIntegration({
94
- measurementId: 'G-XXXXXXXXXX', // Substitua pelo seu ID
95
- }),
96
- ];
97
-
98
- function App() {
99
- return (
100
- <ConsentProvider
101
- categories={{ enabledCategories: ['analytics'] }}
102
- texts={{
103
- bannerMessage: 'Nós usamos cookies para analisar o tráfego e melhorar a sua experiência.',
104
- acceptAll: 'Aceitar',
105
- declineAll: 'Recusar',
106
- // Para conformidade com a ANPD, preencha os campos abaixo
107
- controllerInfo: 'Controlado por: Sua Empresa LTDA (CNPJ: XX.XXX.XXX/XXXX-XX)',
108
- contactInfo: 'Contato do DPO: dpo@suaempresa.com',
109
- }}
110
- onConsentGiven={(state) => {
111
- console.log('O usuário deu o primeiro consentimento!', state.preferences);
112
- }}
113
- >
114
- {/* 2. Adicione o loader de scripts para carregá-los após o consentimento */}
115
- <ConsentScriptLoader integrations={integrations} />
116
-
117
- <SuaAplicacao />
118
- </ConsentProvider>
119
- );
120
- }
121
- ```
122
-
123
- ---
124
-
125
65
  ## 📚 Documentação Completa
126
66
 
127
67
  Para mais detalhes sobre customização, hooks e funcionalidades, consulte os seguintes guias:
128
68
 
69
+ ### 📋 Documentação Principal
70
+ - **[📚 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.
129
71
  - **[Guia da API (`API.md`)](./API.md)**: Referência completa de todos os componentes, hooks e tipos.
130
72
  - **[Guia de Conformidade (`CONFORMIDADE.md`)](./CONFORMIDADE.md)**: Detalhes sobre as funcionalidades de conformidade com a LGPD.
131
73
  - **[Guia de Integrações (`INTEGRACOES.md`)](./INTEGRACOES.md)**: Como usar as integrações nativas e criar as suas.
132
74
 
75
+ ### 🎨 Documentação Interativa (GitHub Pages)
76
+ - **[📖 Storybook - Playground Interativo](https://lucianoedipo.github.io/react-lgpd-consent/storybook/)**: Explore e teste todos os componentes em tempo real com controles interativos.
77
+ - **[⚙️ TypeDoc - Referência de API](https://lucianoedipo.github.io/react-lgpd-consent/docs/)**: Documentação completa da API gerada automaticamente.
78
+ - **[🏠 Portal de Documentação](https://lucianoedipo.github.io/react-lgpd-consent/)**: Página inicial com navegação entre todas as documentações.
133
79
  ---
134
80
 
135
81
  ## 🤝 Como Contribuir
136
-
137
- Contribuições são muito bem-vindas! Este é um projeto open-source para a comunidade brasileira.
138
-
139
- 1. **Reporte Bugs ou Sugira Melhorias**: Abra uma [Issue no GitHub](https://github.com/lucianoedipo/react-lgpd-consent/issues).
140
- 2. **Envie um Pull Request**: Siga as instruções no nosso [Guia de Desenvolvimento (`DEVELOPMENT.md`)](./DEVELOPMENT.md).
82
+ 1. Abra uma [Issue](https://github.com/lucianoedipo/react-lgpd-consent/issues) para bugs ou melhorias.
83
+ 2. Siga o Guia de Desenvolvimento em `DEVELOPMENT.md` para enviar um PR.
141
84
 
142
85
  ---
143
-
144
86
  ## 📄 Licença
145
87
 
146
- Este projeto está licenciado sob a **MIT License**. Veja o arquivo [LICENSE](./LICENSE) para mais detalhes.
88
+ MIT veja o arquivo `LICENSE`.
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  PreferencesModal
3
- } from "./chunk-GPLNN3FD.js";
3
+ } from "./chunk-7D2F6JFW.js";
4
4
  export {
5
5
  PreferencesModal
6
6
  };
@@ -737,6 +737,7 @@ var linkStyles = {
737
737
  };
738
738
  function Branding({ variant, hidden = false }) {
739
739
  const texts = useConsentTexts();
740
+ const designTokens = useDesignTokens();
740
741
  if (hidden) return null;
741
742
  return /* @__PURE__ */ jsxs(
742
743
  Typography,
@@ -744,7 +745,7 @@ function Branding({ variant, hidden = false }) {
744
745
  variant: "caption",
745
746
  sx: (theme) => ({
746
747
  ...brandingStyles[variant],
747
- color: theme.palette.text.secondary
748
+ color: designTokens?.colors?.text ?? theme.palette.text.secondary
748
749
  }),
749
750
  children: [
750
751
  texts.brandingPoweredBy || "fornecido por",
@@ -757,7 +758,7 @@ function Branding({ variant, hidden = false }) {
757
758
  rel: "noopener noreferrer",
758
759
  sx: (theme) => ({
759
760
  ...linkStyles,
760
- color: theme.palette.primary.main
761
+ color: designTokens?.colors?.primary ?? theme.palette.primary.main
761
762
  }),
762
763
  children: "L\xC9dipO.eti.br"
763
764
  }
@@ -864,7 +865,13 @@ function CookieBanner({
864
865
  width: designTokens?.layout?.width?.desktop ?? "100%",
865
866
  p: 2
866
867
  };
867
- const backdropColor = designTokens?.layout?.backdrop === false ? "transparent" : typeof designTokens?.layout?.backdrop === "string" ? designTokens.layout.backdrop : "rgba(0, 0, 0, 0.4)";
868
+ let backdropColor = "rgba(0, 0, 0, 0.4)";
869
+ const backdropToken = designTokens?.layout?.backdrop;
870
+ if (backdropToken === false) {
871
+ backdropColor = "transparent";
872
+ } else if (typeof backdropToken === "string") {
873
+ backdropColor = backdropToken;
874
+ }
868
875
  if (blocking) {
869
876
  return /* @__PURE__ */ jsxs2(Fragment, { children: [
870
877
  /* @__PURE__ */ jsx5(
@@ -933,6 +940,7 @@ function FloatingPreferencesButton({
933
940
  const { openPreferences, consented } = useConsent();
934
941
  const texts = useConsentTexts();
935
942
  const safeTheme = useThemeWithFallbacks();
943
+ const designTokens = useDesignTokens();
936
944
  logger.componentRender("FloatingPreferencesButton", {
937
945
  position,
938
946
  offset,
@@ -972,9 +980,9 @@ function FloatingPreferencesButton({
972
980
  onClick: openPreferences,
973
981
  sx: {
974
982
  ...getPosition(),
975
- backgroundColor: safeTheme.palette.primary.main,
983
+ backgroundColor: designTokens?.colors?.primary ?? safeTheme.palette.primary.main,
976
984
  "&:hover": {
977
- backgroundColor: safeTheme.palette.primary.dark
985
+ backgroundColor: designTokens?.colors?.primary ? designTokens?.colors?.primary : safeTheme.palette.primary.dark
978
986
  },
979
987
  transition: `all ${safeTheme.transitions.duration.short}ms`
980
988
  },
@@ -988,7 +996,7 @@ function FloatingPreferencesButton({
988
996
  // src/context/ConsentContext.tsx
989
997
  import { jsx as jsx7, jsxs as jsxs3 } from "react/jsx-runtime";
990
998
  var PreferencesModal = React5.lazy(
991
- () => import("./PreferencesModal-HTTMUZND.js").then((m) => ({
999
+ () => import("./PreferencesModal-XYBFROAB.js").then((m) => ({
992
1000
  default: m.PreferencesModal
993
1001
  }))
994
1002
  );
@@ -1122,6 +1130,8 @@ function ConsentProvider({
1122
1130
  FloatingPreferencesButtonComponent,
1123
1131
  floatingPreferencesButtonProps = {},
1124
1132
  disableFloatingPreferencesButton = false,
1133
+ blocking = false,
1134
+ blockingStrategy = "auto",
1125
1135
  hideBranding = false,
1126
1136
  onConsentGiven,
1127
1137
  onPreferencesSaved,
@@ -1212,6 +1222,12 @@ function ConsentProvider({
1212
1222
  _registerGlobalOpenPreferences(api.openPreferences);
1213
1223
  return () => _unregisterGlobalOpenPreferences();
1214
1224
  }, [api.openPreferences]);
1225
+ const providerBackdropColor = React5.useMemo(() => {
1226
+ const backdrop = designTokens?.layout?.backdrop;
1227
+ if (backdrop === false) return "transparent";
1228
+ if (typeof backdrop === "string") return backdrop;
1229
+ return "rgba(0, 0, 0, 0.4)";
1230
+ }, [designTokens]);
1215
1231
  return /* @__PURE__ */ jsx7(SafeThemeProvider, { theme: appliedTheme, children: /* @__PURE__ */ jsx7(StateCtx.Provider, { value: state, children: /* @__PURE__ */ jsx7(ActionsCtx.Provider, { value: api, children: /* @__PURE__ */ jsx7(TextsCtx.Provider, { value: texts, children: /* @__PURE__ */ jsx7(HydrationCtx.Provider, { value: isHydrated, children: /* @__PURE__ */ jsx7(DesignProvider, { tokens: designTokens, children: /* @__PURE__ */ jsxs3(
1216
1232
  CategoriesProvider,
1217
1233
  {
@@ -1230,6 +1246,22 @@ function ConsentProvider({
1230
1246
  ...preferencesModalProps
1231
1247
  }
1232
1248
  ) : /* @__PURE__ */ jsx7(PreferencesModal, { hideBranding }) }),
1249
+ blocking && isHydrated && !state.consented && blockingStrategy === "provider" && /* @__PURE__ */ jsx7(
1250
+ "div",
1251
+ {
1252
+ style: {
1253
+ position: "fixed",
1254
+ top: 0,
1255
+ left: 0,
1256
+ right: 0,
1257
+ bottom: 0,
1258
+ backgroundColor: providerBackdropColor,
1259
+ zIndex: 1299
1260
+ },
1261
+ "data-testid": "lgpd-provider-overlay",
1262
+ "aria-hidden": true
1263
+ }
1264
+ ),
1233
1265
  !state.consented && isHydrated && (CookieBannerComponent ? /* @__PURE__ */ jsx7(
1234
1266
  CookieBannerComponent,
1235
1267
  {
@@ -1238,9 +1270,17 @@ function ConsentProvider({
1238
1270
  rejectAll: api.rejectAll,
1239
1271
  openPreferences: api.openPreferences,
1240
1272
  texts,
1273
+ blocking,
1274
+ ...cookieBannerProps
1275
+ }
1276
+ ) : /* @__PURE__ */ jsx7(
1277
+ CookieBanner,
1278
+ {
1279
+ blocking,
1280
+ hideBranding,
1241
1281
  ...cookieBannerProps
1242
1282
  }
1243
- ) : /* @__PURE__ */ jsx7(CookieBanner, {})),
1283
+ )),
1244
1284
  state.consented && !disableFloatingPreferencesButton && (FloatingPreferencesButtonComponent ? /* @__PURE__ */ jsx7(
1245
1285
  FloatingPreferencesButtonComponent,
1246
1286
  {
@@ -1248,7 +1288,10 @@ function ConsentProvider({
1248
1288
  consented: api.consented,
1249
1289
  ...floatingPreferencesButtonProps
1250
1290
  }
1251
- ) : /* @__PURE__ */ jsx7(FloatingPreferencesButton, {}))
1291
+ ) : (
1292
+ // Encaminha `floatingPreferencesButtonProps` para o componente padrão
1293
+ /* @__PURE__ */ jsx7(FloatingPreferencesButton, { ...floatingPreferencesButtonProps })
1294
+ ))
1252
1295
  ]
1253
1296
  }
1254
1297
  ) }) }) }) }) }) });
@@ -1324,6 +1367,7 @@ function PreferencesModal2({
1324
1367
  }) {
1325
1368
  const { preferences, setPreferences, closePreferences, isModalOpen } = useConsent();
1326
1369
  const texts = useConsentTexts();
1370
+ const designTokens = useDesignTokens();
1327
1371
  const { toggleableCategories } = useCategories();
1328
1372
  const [tempPreferences, setTempPreferences] = useState2(() => {
1329
1373
  const initialPrefs = { necessary: true };
@@ -1350,9 +1394,23 @@ function PreferencesModal2({
1350
1394
  closePreferences();
1351
1395
  };
1352
1396
  return /* @__PURE__ */ jsxs4(Dialog, { "aria-labelledby": "cookie-pref-title", open, onClose: handleCancel, ...DialogProps2, children: [
1353
- /* @__PURE__ */ jsx8(DialogTitle, { id: "cookie-pref-title", children: texts.modalTitle }),
1354
- /* @__PURE__ */ jsxs4(DialogContent, { dividers: true, children: [
1355
- /* @__PURE__ */ jsx8(Typography3, { variant: "body2", sx: { mb: 2 }, children: texts.modalIntro }),
1397
+ /* @__PURE__ */ jsx8(
1398
+ DialogTitle,
1399
+ {
1400
+ id: "cookie-pref-title",
1401
+ sx: { fontSize: designTokens?.typography?.fontSize?.modal ?? void 0 },
1402
+ children: texts.modalTitle
1403
+ }
1404
+ ),
1405
+ /* @__PURE__ */ jsxs4(DialogContent, { dividers: true, sx: { p: designTokens?.spacing?.padding?.modal ?? void 0 }, children: [
1406
+ /* @__PURE__ */ jsx8(
1407
+ Typography3,
1408
+ {
1409
+ variant: "body2",
1410
+ sx: { mb: 2, fontSize: designTokens?.typography?.fontSize?.modal ?? void 0 },
1411
+ children: texts.modalIntro
1412
+ }
1413
+ ),
1356
1414
  /* @__PURE__ */ jsxs4(FormGroup, { children: [
1357
1415
  toggleableCategories.map((category) => /* @__PURE__ */ jsx8(
1358
1416
  FormControlLabel,
package/dist/index.cjs CHANGED
@@ -761,6 +761,7 @@ var init_DesignContext = __esm({
761
761
  // src/components/Branding.tsx
762
762
  function Branding({ variant, hidden = false }) {
763
763
  const texts = useConsentTexts();
764
+ const designTokens = useDesignTokens();
764
765
  if (hidden) return null;
765
766
  return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
766
767
  import_Typography.default,
@@ -768,7 +769,7 @@ function Branding({ variant, hidden = false }) {
768
769
  variant: "caption",
769
770
  sx: (theme) => ({
770
771
  ...brandingStyles[variant],
771
- color: theme.palette.text.secondary
772
+ color: designTokens?.colors?.text ?? theme.palette.text.secondary
772
773
  }),
773
774
  children: [
774
775
  texts.brandingPoweredBy || "fornecido por",
@@ -781,7 +782,7 @@ function Branding({ variant, hidden = false }) {
781
782
  rel: "noopener noreferrer",
782
783
  sx: (theme) => ({
783
784
  ...linkStyles,
784
- color: theme.palette.primary.main
785
+ color: designTokens?.colors?.primary ?? theme.palette.primary.main
785
786
  }),
786
787
  children: "L\xC9dipO.eti.br"
787
788
  }
@@ -795,6 +796,7 @@ var init_Branding = __esm({
795
796
  "src/components/Branding.tsx"() {
796
797
  "use strict";
797
798
  init_useConsent();
799
+ init_DesignContext();
798
800
  import_Link = __toESM(require("@mui/material/Link"), 1);
799
801
  import_Typography = __toESM(require("@mui/material/Typography"), 1);
800
802
  import_jsx_runtime4 = require("react/jsx-runtime");
@@ -923,7 +925,13 @@ function CookieBanner({
923
925
  width: designTokens?.layout?.width?.desktop ?? "100%",
924
926
  p: 2
925
927
  };
926
- const backdropColor = designTokens?.layout?.backdrop === false ? "transparent" : typeof designTokens?.layout?.backdrop === "string" ? designTokens.layout.backdrop : "rgba(0, 0, 0, 0.4)";
928
+ let backdropColor = "rgba(0, 0, 0, 0.4)";
929
+ const backdropToken = designTokens?.layout?.backdrop;
930
+ if (backdropToken === false) {
931
+ backdropColor = "transparent";
932
+ } else if (typeof backdropToken === "string") {
933
+ backdropColor = backdropToken;
934
+ }
927
935
  if (blocking) {
928
936
  return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_jsx_runtime5.Fragment, { children: [
929
937
  /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
@@ -1005,6 +1013,7 @@ function FloatingPreferencesButton({
1005
1013
  const { openPreferences, consented } = useConsent();
1006
1014
  const texts = useConsentTexts();
1007
1015
  const safeTheme = useThemeWithFallbacks();
1016
+ const designTokens = useDesignTokens();
1008
1017
  logger.componentRender("FloatingPreferencesButton", {
1009
1018
  position,
1010
1019
  offset,
@@ -1044,9 +1053,9 @@ function FloatingPreferencesButton({
1044
1053
  onClick: openPreferences,
1045
1054
  sx: {
1046
1055
  ...getPosition(),
1047
- backgroundColor: safeTheme.palette.primary.main,
1056
+ backgroundColor: designTokens?.colors?.primary ?? safeTheme.palette.primary.main,
1048
1057
  "&:hover": {
1049
- backgroundColor: safeTheme.palette.primary.dark
1058
+ backgroundColor: designTokens?.colors?.primary ? designTokens?.colors?.primary : safeTheme.palette.primary.dark
1050
1059
  },
1051
1060
  transition: `all ${safeTheme.transitions.duration.short}ms`
1052
1061
  },
@@ -1064,6 +1073,7 @@ var init_FloatingPreferencesButton = __esm({
1064
1073
  import_Fab = __toESM(require("@mui/material/Fab"), 1);
1065
1074
  import_Tooltip = __toESM(require("@mui/material/Tooltip"), 1);
1066
1075
  import_styles3 = require("@mui/material/styles");
1076
+ init_DesignContext();
1067
1077
  init_useConsent();
1068
1078
  init_logger();
1069
1079
  import_jsx_runtime6 = require("react/jsx-runtime");
@@ -1160,6 +1170,8 @@ function ConsentProvider({
1160
1170
  FloatingPreferencesButtonComponent,
1161
1171
  floatingPreferencesButtonProps = {},
1162
1172
  disableFloatingPreferencesButton = false,
1173
+ blocking = false,
1174
+ blockingStrategy = "auto",
1163
1175
  hideBranding = false,
1164
1176
  onConsentGiven,
1165
1177
  onPreferencesSaved,
@@ -1250,6 +1262,12 @@ function ConsentProvider({
1250
1262
  _registerGlobalOpenPreferences(api.openPreferences);
1251
1263
  return () => _unregisterGlobalOpenPreferences();
1252
1264
  }, [api.openPreferences]);
1265
+ const providerBackdropColor = React5.useMemo(() => {
1266
+ const backdrop = designTokens?.layout?.backdrop;
1267
+ if (backdrop === false) return "transparent";
1268
+ if (typeof backdrop === "string") return backdrop;
1269
+ return "rgba(0, 0, 0, 0.4)";
1270
+ }, [designTokens]);
1253
1271
  return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(SafeThemeProvider, { theme: appliedTheme, children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(StateCtx.Provider, { value: state, children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(ActionsCtx.Provider, { value: api, children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(TextsCtx.Provider, { value: texts, children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(HydrationCtx.Provider, { value: isHydrated, children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(DesignProvider, { tokens: designTokens, children: /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
1254
1272
  CategoriesProvider,
1255
1273
  {
@@ -1268,6 +1286,22 @@ function ConsentProvider({
1268
1286
  ...preferencesModalProps
1269
1287
  }
1270
1288
  ) : /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(PreferencesModal, { hideBranding }) }),
1289
+ blocking && isHydrated && !state.consented && blockingStrategy === "provider" && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
1290
+ "div",
1291
+ {
1292
+ style: {
1293
+ position: "fixed",
1294
+ top: 0,
1295
+ left: 0,
1296
+ right: 0,
1297
+ bottom: 0,
1298
+ backgroundColor: providerBackdropColor,
1299
+ zIndex: 1299
1300
+ },
1301
+ "data-testid": "lgpd-provider-overlay",
1302
+ "aria-hidden": true
1303
+ }
1304
+ ),
1271
1305
  !state.consented && isHydrated && (CookieBannerComponent ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
1272
1306
  CookieBannerComponent,
1273
1307
  {
@@ -1276,9 +1310,17 @@ function ConsentProvider({
1276
1310
  rejectAll: api.rejectAll,
1277
1311
  openPreferences: api.openPreferences,
1278
1312
  texts,
1313
+ blocking,
1314
+ ...cookieBannerProps
1315
+ }
1316
+ ) : /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
1317
+ CookieBanner,
1318
+ {
1319
+ blocking,
1320
+ hideBranding,
1279
1321
  ...cookieBannerProps
1280
1322
  }
1281
- ) : /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(CookieBanner, {})),
1323
+ )),
1282
1324
  state.consented && !disableFloatingPreferencesButton && (FloatingPreferencesButtonComponent ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
1283
1325
  FloatingPreferencesButtonComponent,
1284
1326
  {
@@ -1286,7 +1328,10 @@ function ConsentProvider({
1286
1328
  consented: api.consented,
1287
1329
  ...floatingPreferencesButtonProps
1288
1330
  }
1289
- ) : /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(FloatingPreferencesButton, {}))
1331
+ ) : (
1332
+ // Encaminha `floatingPreferencesButtonProps` para o componente padrão
1333
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(FloatingPreferencesButton, { ...floatingPreferencesButtonProps })
1334
+ ))
1290
1335
  ]
1291
1336
  }
1292
1337
  ) }) }) }) }) }) });
@@ -1438,6 +1483,7 @@ function PreferencesModal2({
1438
1483
  }) {
1439
1484
  const { preferences, setPreferences, closePreferences, isModalOpen } = useConsent();
1440
1485
  const texts = useConsentTexts();
1486
+ const designTokens = useDesignTokens();
1441
1487
  const { toggleableCategories } = useCategories();
1442
1488
  const [tempPreferences, setTempPreferences] = (0, import_react2.useState)(() => {
1443
1489
  const initialPrefs = { necessary: true };
@@ -1464,9 +1510,23 @@ function PreferencesModal2({
1464
1510
  closePreferences();
1465
1511
  };
1466
1512
  return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(import_Dialog.default, { "aria-labelledby": "cookie-pref-title", open, onClose: handleCancel, ...DialogProps2, children: [
1467
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_DialogTitle.default, { id: "cookie-pref-title", children: texts.modalTitle }),
1468
- /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(import_DialogContent.default, { dividers: true, children: [
1469
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_Typography3.default, { variant: "body2", sx: { mb: 2 }, children: texts.modalIntro }),
1513
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
1514
+ import_DialogTitle.default,
1515
+ {
1516
+ id: "cookie-pref-title",
1517
+ sx: { fontSize: designTokens?.typography?.fontSize?.modal ?? void 0 },
1518
+ children: texts.modalTitle
1519
+ }
1520
+ ),
1521
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(import_DialogContent.default, { dividers: true, sx: { p: designTokens?.spacing?.padding?.modal ?? void 0 }, children: [
1522
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
1523
+ import_Typography3.default,
1524
+ {
1525
+ variant: "body2",
1526
+ sx: { mb: 2, fontSize: designTokens?.typography?.fontSize?.modal ?? void 0 },
1527
+ children: texts.modalIntro
1528
+ }
1529
+ ),
1470
1530
  /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(import_FormGroup.default, { children: [
1471
1531
  toggleableCategories.map((category) => /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
1472
1532
  import_FormControlLabel.default,
@@ -1511,6 +1571,7 @@ var init_PreferencesModal = __esm({
1511
1571
  import_react2 = require("react");
1512
1572
  init_CategoriesContext();
1513
1573
  init_useConsent();
1574
+ init_DesignContext();
1514
1575
  init_Branding();
1515
1576
  import_jsx_runtime8 = require("react/jsx-runtime");
1516
1577
  }
package/dist/index.d.cts CHANGED
@@ -567,7 +567,7 @@ interface DesignTokens {
567
567
  mobile?: string;
568
568
  desktop?: string;
569
569
  };
570
- backdrop?: boolean;
570
+ backdrop?: boolean | string;
571
571
  };
572
572
  }
573
573
  /**
@@ -713,6 +713,22 @@ interface ConsentProviderProps {
713
713
  * - `true`: Banner bloqueia interação até decisão (compliance rigorosa)
714
714
  */
715
715
  blocking?: boolean;
716
+ /**
717
+ * Estratégia de bloqueio quando `blocking` estiver habilitado.
718
+ * - 'auto' (padrão):
719
+ * - Se usar o banner padrão da lib, o bloqueio visual/funcional fica a cargo do próprio banner.
720
+ * - Se usar `CookieBannerComponent` custom, o Provider NÃO cria overlay; o bloqueio fica a cargo do componente custom (compatibilidade atual).
721
+ * - 'provider': o Provider cria um overlay de bloqueio por cima da aplicação (e abaixo do banner),
722
+ * garantindo que cliques sejam bloqueados, independentemente do banner custom implementar ou não esse comportamento.
723
+ * - 'component': nenhum overlay do Provider; espera-se que o banner (padrão ou custom) trate o bloqueio.
724
+ *
725
+ * Observações:
726
+ * - Visual do overlay do Provider controlado por `designTokens.layout.backdrop`:
727
+ * - `false`: overlay transparente (bloqueia cliques sem escurecer — útil quando o app já possui um dark-filter visual próprio).
728
+ * - `string` (ex.: 'rgba(0,0,0,0.4)'): overlay com escurecimento gerenciado pela lib.
729
+ * - A11y: recomenda-se que o banner use semântica de diálogo (role="dialog", aria-modal="true") e trap de foco.
730
+ */
731
+ blockingStrategy?: 'auto' | 'provider' | 'component';
716
732
  /** Oculta o branding "fornecido por LÉdipO.eti.br" dos componentes. */
717
733
  hideBranding?: boolean;
718
734
  /**
@@ -776,6 +792,12 @@ interface CustomCookieBannerProps {
776
792
  rejectAll: () => void;
777
793
  openPreferences: () => void;
778
794
  texts: ConsentTexts;
795
+ /**
796
+ * Indica se o modo bloqueante está ativo no contexto.
797
+ * Esta prop é apenas informativa para banners customizados ajustarem sua UI.
798
+ * O bloqueio funcional pode ser garantido pelo Provider quando `blockingStrategy='provider'`.
799
+ */
800
+ blocking?: boolean;
779
801
  }
780
802
  /**
781
803
  * Props esperadas por um componente customizado de PreferencesModal.
@@ -883,7 +905,7 @@ interface ConsentContextValue {
883
905
  * </ConsentProvider>
884
906
  * ```
885
907
  */
886
- declare function ConsentProvider({ initialState, categories, texts: textsProp, theme, designTokens, PreferencesModalComponent, preferencesModalProps, CookieBannerComponent, cookieBannerProps, FloatingPreferencesButtonComponent, floatingPreferencesButtonProps, disableFloatingPreferencesButton, hideBranding, onConsentGiven, onPreferencesSaved, cookie: cookieOpts, disableDeveloperGuidance, children, }: Readonly<ConsentProviderProps>): react_jsx_runtime.JSX.Element;
908
+ declare function ConsentProvider({ initialState, categories, texts: textsProp, theme, designTokens, PreferencesModalComponent, preferencesModalProps, CookieBannerComponent, cookieBannerProps, FloatingPreferencesButtonComponent, floatingPreferencesButtonProps, disableFloatingPreferencesButton, blocking, blockingStrategy, hideBranding, onConsentGiven, onPreferencesSaved, cookie: cookieOpts, disableDeveloperGuidance, children, }: Readonly<ConsentProviderProps>): react_jsx_runtime.JSX.Element;
887
909
  declare const defaultTexts: ConsentTexts;
888
910
 
889
911
  /**
@@ -916,7 +938,7 @@ declare const defaultTexts: ConsentTexts;
916
938
  * - **`setPreferences(preferences)`**: Define múltiplas categorias de uma vez
917
939
  * - **`openPreferences()`**: Abre o modal de preferências
918
940
  * - **`closePreferences()`**: Fecha o modal de preferências
919
- * - **`resetConsent()`**: Limpa todo consentimento (volta ao estado inicial)
941
+ * - **`resetConsent()`**: Limpa all consentimento (volta ao estado inicial)
920
942
  *
921
943
  * ### Performance e SSR
922
944
  * - O hook é otimizado com `useMemo` interno para evitar re-renders desnecessários