react-lgpd-consent 0.3.2 → 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-JUZQJHQW.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,6 +865,13 @@ function CookieBanner({
864
865
  width: designTokens?.layout?.width?.desktop ?? "100%",
865
866
  p: 2
866
867
  };
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
+ }
867
875
  if (blocking) {
868
876
  return /* @__PURE__ */ jsxs2(Fragment, { children: [
869
877
  /* @__PURE__ */ jsx5(
@@ -875,7 +883,7 @@ function CookieBanner({
875
883
  left: 0,
876
884
  right: 0,
877
885
  bottom: 0,
878
- backgroundColor: designTokens?.layout?.backdrop ? "rgba(0, 0, 0, 0.5)" : "transparent",
886
+ backgroundColor: backdropColor,
879
887
  zIndex: 1299
880
888
  }
881
889
  }
@@ -932,6 +940,7 @@ function FloatingPreferencesButton({
932
940
  const { openPreferences, consented } = useConsent();
933
941
  const texts = useConsentTexts();
934
942
  const safeTheme = useThemeWithFallbacks();
943
+ const designTokens = useDesignTokens();
935
944
  logger.componentRender("FloatingPreferencesButton", {
936
945
  position,
937
946
  offset,
@@ -971,9 +980,9 @@ function FloatingPreferencesButton({
971
980
  onClick: openPreferences,
972
981
  sx: {
973
982
  ...getPosition(),
974
- backgroundColor: safeTheme.palette.primary.main,
983
+ backgroundColor: designTokens?.colors?.primary ?? safeTheme.palette.primary.main,
975
984
  "&:hover": {
976
- backgroundColor: safeTheme.palette.primary.dark
985
+ backgroundColor: designTokens?.colors?.primary ? designTokens?.colors?.primary : safeTheme.palette.primary.dark
977
986
  },
978
987
  transition: `all ${safeTheme.transitions.duration.short}ms`
979
988
  },
@@ -987,7 +996,7 @@ function FloatingPreferencesButton({
987
996
  // src/context/ConsentContext.tsx
988
997
  import { jsx as jsx7, jsxs as jsxs3 } from "react/jsx-runtime";
989
998
  var PreferencesModal = React5.lazy(
990
- () => import("./PreferencesModal-7RSEEVUK.js").then((m) => ({
999
+ () => import("./PreferencesModal-XYBFROAB.js").then((m) => ({
991
1000
  default: m.PreferencesModal
992
1001
  }))
993
1002
  );
@@ -1121,6 +1130,8 @@ function ConsentProvider({
1121
1130
  FloatingPreferencesButtonComponent,
1122
1131
  floatingPreferencesButtonProps = {},
1123
1132
  disableFloatingPreferencesButton = false,
1133
+ blocking = false,
1134
+ blockingStrategy = "auto",
1124
1135
  hideBranding = false,
1125
1136
  onConsentGiven,
1126
1137
  onPreferencesSaved,
@@ -1211,6 +1222,12 @@ function ConsentProvider({
1211
1222
  _registerGlobalOpenPreferences(api.openPreferences);
1212
1223
  return () => _unregisterGlobalOpenPreferences();
1213
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]);
1214
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(
1215
1232
  CategoriesProvider,
1216
1233
  {
@@ -1229,6 +1246,22 @@ function ConsentProvider({
1229
1246
  ...preferencesModalProps
1230
1247
  }
1231
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
+ ),
1232
1265
  !state.consented && isHydrated && (CookieBannerComponent ? /* @__PURE__ */ jsx7(
1233
1266
  CookieBannerComponent,
1234
1267
  {
@@ -1237,9 +1270,17 @@ function ConsentProvider({
1237
1270
  rejectAll: api.rejectAll,
1238
1271
  openPreferences: api.openPreferences,
1239
1272
  texts,
1273
+ blocking,
1274
+ ...cookieBannerProps
1275
+ }
1276
+ ) : /* @__PURE__ */ jsx7(
1277
+ CookieBanner,
1278
+ {
1279
+ blocking,
1280
+ hideBranding,
1240
1281
  ...cookieBannerProps
1241
1282
  }
1242
- ) : /* @__PURE__ */ jsx7(CookieBanner, {})),
1283
+ )),
1243
1284
  state.consented && !disableFloatingPreferencesButton && (FloatingPreferencesButtonComponent ? /* @__PURE__ */ jsx7(
1244
1285
  FloatingPreferencesButtonComponent,
1245
1286
  {
@@ -1247,7 +1288,10 @@ function ConsentProvider({
1247
1288
  consented: api.consented,
1248
1289
  ...floatingPreferencesButtonProps
1249
1290
  }
1250
- ) : /* @__PURE__ */ jsx7(FloatingPreferencesButton, {}))
1291
+ ) : (
1292
+ // Encaminha `floatingPreferencesButtonProps` para o componente padrão
1293
+ /* @__PURE__ */ jsx7(FloatingPreferencesButton, { ...floatingPreferencesButtonProps })
1294
+ ))
1251
1295
  ]
1252
1296
  }
1253
1297
  ) }) }) }) }) }) });
@@ -1323,6 +1367,7 @@ function PreferencesModal2({
1323
1367
  }) {
1324
1368
  const { preferences, setPreferences, closePreferences, isModalOpen } = useConsent();
1325
1369
  const texts = useConsentTexts();
1370
+ const designTokens = useDesignTokens();
1326
1371
  const { toggleableCategories } = useCategories();
1327
1372
  const [tempPreferences, setTempPreferences] = useState2(() => {
1328
1373
  const initialPrefs = { necessary: true };
@@ -1349,9 +1394,23 @@ function PreferencesModal2({
1349
1394
  closePreferences();
1350
1395
  };
1351
1396
  return /* @__PURE__ */ jsxs4(Dialog, { "aria-labelledby": "cookie-pref-title", open, onClose: handleCancel, ...DialogProps2, children: [
1352
- /* @__PURE__ */ jsx8(DialogTitle, { id: "cookie-pref-title", children: texts.modalTitle }),
1353
- /* @__PURE__ */ jsxs4(DialogContent, { dividers: true, children: [
1354
- /* @__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
+ ),
1355
1414
  /* @__PURE__ */ jsxs4(FormGroup, { children: [
1356
1415
  toggleableCategories.map((category) => /* @__PURE__ */ jsx8(
1357
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,6 +925,13 @@ function CookieBanner({
923
925
  width: designTokens?.layout?.width?.desktop ?? "100%",
924
926
  p: 2
925
927
  };
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
+ }
926
935
  if (blocking) {
927
936
  return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_jsx_runtime5.Fragment, { children: [
928
937
  /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
@@ -934,7 +943,7 @@ function CookieBanner({
934
943
  left: 0,
935
944
  right: 0,
936
945
  bottom: 0,
937
- backgroundColor: designTokens?.layout?.backdrop ? "rgba(0, 0, 0, 0.5)" : "transparent",
946
+ backgroundColor: backdropColor,
938
947
  zIndex: 1299
939
948
  }
940
949
  }
@@ -1004,6 +1013,7 @@ function FloatingPreferencesButton({
1004
1013
  const { openPreferences, consented } = useConsent();
1005
1014
  const texts = useConsentTexts();
1006
1015
  const safeTheme = useThemeWithFallbacks();
1016
+ const designTokens = useDesignTokens();
1007
1017
  logger.componentRender("FloatingPreferencesButton", {
1008
1018
  position,
1009
1019
  offset,
@@ -1043,9 +1053,9 @@ function FloatingPreferencesButton({
1043
1053
  onClick: openPreferences,
1044
1054
  sx: {
1045
1055
  ...getPosition(),
1046
- backgroundColor: safeTheme.palette.primary.main,
1056
+ backgroundColor: designTokens?.colors?.primary ?? safeTheme.palette.primary.main,
1047
1057
  "&:hover": {
1048
- backgroundColor: safeTheme.palette.primary.dark
1058
+ backgroundColor: designTokens?.colors?.primary ? designTokens?.colors?.primary : safeTheme.palette.primary.dark
1049
1059
  },
1050
1060
  transition: `all ${safeTheme.transitions.duration.short}ms`
1051
1061
  },
@@ -1063,6 +1073,7 @@ var init_FloatingPreferencesButton = __esm({
1063
1073
  import_Fab = __toESM(require("@mui/material/Fab"), 1);
1064
1074
  import_Tooltip = __toESM(require("@mui/material/Tooltip"), 1);
1065
1075
  import_styles3 = require("@mui/material/styles");
1076
+ init_DesignContext();
1066
1077
  init_useConsent();
1067
1078
  init_logger();
1068
1079
  import_jsx_runtime6 = require("react/jsx-runtime");
@@ -1159,6 +1170,8 @@ function ConsentProvider({
1159
1170
  FloatingPreferencesButtonComponent,
1160
1171
  floatingPreferencesButtonProps = {},
1161
1172
  disableFloatingPreferencesButton = false,
1173
+ blocking = false,
1174
+ blockingStrategy = "auto",
1162
1175
  hideBranding = false,
1163
1176
  onConsentGiven,
1164
1177
  onPreferencesSaved,
@@ -1249,6 +1262,12 @@ function ConsentProvider({
1249
1262
  _registerGlobalOpenPreferences(api.openPreferences);
1250
1263
  return () => _unregisterGlobalOpenPreferences();
1251
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]);
1252
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)(
1253
1272
  CategoriesProvider,
1254
1273
  {
@@ -1267,6 +1286,22 @@ function ConsentProvider({
1267
1286
  ...preferencesModalProps
1268
1287
  }
1269
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
+ ),
1270
1305
  !state.consented && isHydrated && (CookieBannerComponent ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
1271
1306
  CookieBannerComponent,
1272
1307
  {
@@ -1275,9 +1310,17 @@ function ConsentProvider({
1275
1310
  rejectAll: api.rejectAll,
1276
1311
  openPreferences: api.openPreferences,
1277
1312
  texts,
1313
+ blocking,
1314
+ ...cookieBannerProps
1315
+ }
1316
+ ) : /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
1317
+ CookieBanner,
1318
+ {
1319
+ blocking,
1320
+ hideBranding,
1278
1321
  ...cookieBannerProps
1279
1322
  }
1280
- ) : /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(CookieBanner, {})),
1323
+ )),
1281
1324
  state.consented && !disableFloatingPreferencesButton && (FloatingPreferencesButtonComponent ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
1282
1325
  FloatingPreferencesButtonComponent,
1283
1326
  {
@@ -1285,7 +1328,10 @@ function ConsentProvider({
1285
1328
  consented: api.consented,
1286
1329
  ...floatingPreferencesButtonProps
1287
1330
  }
1288
- ) : /* @__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
+ ))
1289
1335
  ]
1290
1336
  }
1291
1337
  ) }) }) }) }) }) });
@@ -1437,6 +1483,7 @@ function PreferencesModal2({
1437
1483
  }) {
1438
1484
  const { preferences, setPreferences, closePreferences, isModalOpen } = useConsent();
1439
1485
  const texts = useConsentTexts();
1486
+ const designTokens = useDesignTokens();
1440
1487
  const { toggleableCategories } = useCategories();
1441
1488
  const [tempPreferences, setTempPreferences] = (0, import_react2.useState)(() => {
1442
1489
  const initialPrefs = { necessary: true };
@@ -1463,9 +1510,23 @@ function PreferencesModal2({
1463
1510
  closePreferences();
1464
1511
  };
1465
1512
  return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(import_Dialog.default, { "aria-labelledby": "cookie-pref-title", open, onClose: handleCancel, ...DialogProps2, children: [
1466
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_DialogTitle.default, { id: "cookie-pref-title", children: texts.modalTitle }),
1467
- /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(import_DialogContent.default, { dividers: true, children: [
1468
- /* @__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
+ ),
1469
1530
  /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(import_FormGroup.default, { children: [
1470
1531
  toggleableCategories.map((category) => /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
1471
1532
  import_FormControlLabel.default,
@@ -1510,6 +1571,7 @@ var init_PreferencesModal = __esm({
1510
1571
  import_react2 = require("react");
1511
1572
  init_CategoriesContext();
1512
1573
  init_useConsent();
1574
+ init_DesignContext();
1513
1575
  init_Branding();
1514
1576
  import_jsx_runtime8 = require("react/jsx-runtime");
1515
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
@@ -1972,7 +1994,7 @@ interface CookieBannerProps {
1972
1994
  * <ConsentProvider CookieBannerComponent={CustomBanner}>
1973
1995
  * ```
1974
1996
  *
1975
- * @param props - Propriedades para customizar comportamento e aparência do banner
1997
+ * @param props - Propriedades para customizar comportamento e aparência do banner (tipado via CookieBannerProps)
1976
1998
  * @returns Banner de consentimento ou `null` se não deve ser exibido
1977
1999
  *
1978
2000
  * @example Uso básico (renderizado automaticamente pelo ConsentProvider)